@@ -382,7 +382,7 @@ public int CreateTable(Type ty, CreateFlags createFlags = CreateFlags.None)
382
382
{
383
383
var map = GetMapping ( ty , createFlags ) ;
384
384
385
- var query = "create table if not exists \" " + map . TableName + "\" (\n " ;
385
+ var query = new StringBuilder ( "create table if not exists \" " ) . Append ( map . TableName ) . Append ( "\" ( \n " ) ;
386
386
387
387
var mapColumns = map . Columns ;
388
388
@@ -391,12 +391,24 @@ public int CreateTable(Type ty, CreateFlags createFlags = CreateFlags.None)
391
391
throw new Exception ( "Table has no (public) columns" ) ;
392
392
}
393
393
394
- var decls = mapColumns . Select ( p => Orm . SqlDecl ( p , StoreDateTimeAsTicks , Serializer , ExtraTypeMappings ) ) ;
395
- var decl = string . Join ( ",\n " , decls . ToArray ( ) ) ;
396
- query += decl ;
397
- query += ")" ;
394
+ if ( map . HasCompositePK )
395
+ {
396
+ var compositePK = mapColumns . Where ( c => c . IsPK ) . ToList ( ) ;
397
+
398
+ var decls = mapColumns . Select ( p => Orm . SqlDecl ( p , StoreDateTimeAsTicks , Serializer , ExtraTypeMappings , map . HasCompositePK ) ) ;
399
+ var decl = string . Join ( ",\n " , decls . ToArray ( ) ) ;
400
+ query . Append ( decl ) . Append ( ",\n " ) ;
401
+ query . Append ( "primary key (" ) . Append ( string . Join ( "," , compositePK . Select ( pk => pk . Name ) ) ) . Append ( ")" ) ;
402
+ query . Append ( ")" ) ;
403
+ }
404
+ else
405
+ {
406
+ var decls = mapColumns . Select ( p => Orm . SqlDecl ( p , StoreDateTimeAsTicks , Serializer , ExtraTypeMappings ) ) ;
407
+ var decl = string . Join ( ",\n " , decls . ToArray ( ) ) ;
408
+ query . Append ( decl ) . Append ( ")" ) ;
409
+ }
398
410
399
- var count = Execute ( query ) ;
411
+ var count = Execute ( query . ToString ( ) ) ;
400
412
401
413
if ( count == 0 )
402
414
{
@@ -582,8 +594,13 @@ private void MigrateTable(TableMapping map)
582
594
583
595
foreach ( var p in toBeAdded )
584
596
{
597
+ if ( p . IsPK )
598
+ {
599
+ throw new NotSupportedException ( "The new column may not have a PRIMARY KEY constraint." ) ;
600
+ }
601
+
585
602
var addCol = "alter table \" " + map . TableName + "\" add column " +
586
- Orm . SqlDecl ( p , StoreDateTimeAsTicks , Serializer , ExtraTypeMappings ) ;
603
+ Orm . SqlDecl ( p , StoreDateTimeAsTicks , Serializer , ExtraTypeMappings , map . HasCompositePK ) ;
587
604
Execute ( addCol ) ;
588
605
}
589
606
}
@@ -822,7 +839,7 @@ public TableQuery<T> Table<T>() where T : class
822
839
/// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute).
823
840
/// </summary>
824
841
/// <param name="pk">
825
- /// The primary key.
842
+ /// The primary key. Needs to be Dictionary<string, object> if table has composite PK.
826
843
/// </param>
827
844
/// <returns>
828
845
/// The object with the given primary key. Throws a not found exception
@@ -832,7 +849,24 @@ public TableQuery<T> Table<T>() where T : class
832
849
public T Get < T > ( object pk ) where T : class
833
850
{
834
851
var map = GetMapping ( typeof ( T ) ) ;
835
- return Query < T > ( map . GetByPrimaryKeySql , pk ) . First ( ) ;
852
+ if ( map . HasCompositePK )
853
+ {
854
+ IDictionary < string , object > compositePK = pk as Dictionary < string , object > ;
855
+ if ( compositePK == null )
856
+ {
857
+ throw new NotSupportedException ( map . TableName + " table has a composite primary key. Make sure primary key is passed in as Dictionary<string, object>." ) ;
858
+ }
859
+ var cpk = map . CompositePK ;
860
+ if ( compositePK . Keys . Intersect ( cpk . Select ( p => p . Name ) ) . Count ( ) < cpk . Length )
861
+ {
862
+ throw new NotSupportedException ( "Cannot get from " + map . TableName + ": CompositePK mismatch. Make sure PK names are valid." ) ;
863
+ }
864
+ return Query < T > ( map . GetByPrimaryKeySql , compositePK . Values . ToArray ( ) ) . First ( ) ;
865
+ }
866
+ else
867
+ {
868
+ return Query < T > ( map . GetByPrimaryKeySql , pk ) . First ( ) ;
869
+ }
836
870
}
837
871
838
872
/// <summary>
@@ -858,7 +892,7 @@ public T Get<T>(Expression<Func<T, bool>> predicate) where T : class
858
892
/// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute).
859
893
/// </summary>
860
894
/// <param name="pk">
861
- /// The primary key.
895
+ /// The primary key. Needs to be Dictionary<string, object> if table has composite PK.
862
896
/// </param>
863
897
/// <returns>
864
898
/// The object with the given primary key or null
@@ -867,8 +901,25 @@ public T Get<T>(Expression<Func<T, bool>> predicate) where T : class
867
901
[ PublicAPI ]
868
902
public T Find < T > ( object pk ) where T : class
869
903
{
870
- var map = GetMapping ( typeof ( T ) ) ;
871
- return Query < T > ( map . GetByPrimaryKeySql , pk ) . FirstOrDefault ( ) ;
904
+ var map = GetMapping ( typeof ( T ) ) ;
905
+ if ( map . HasCompositePK )
906
+ {
907
+ IDictionary < string , object > compositePK = pk as Dictionary < string , object > ;
908
+ if ( compositePK == null )
909
+ {
910
+ throw new NotSupportedException ( map . TableName + " table has a composite primary key. Make sure primary key is passed in as Dictionary<string, object>." ) ;
911
+ }
912
+ var cpk = map . CompositePK ;
913
+ if ( compositePK . Keys . Intersect ( cpk . Select ( p => p . Name ) ) . Count ( ) < cpk . Length )
914
+ {
915
+ throw new NotSupportedException ( "Cannot find in " + map . TableName + ": CompositePK mismatch. Make sure PK names are valid." ) ;
916
+ }
917
+ return Query < T > ( map . GetByPrimaryKeySql , compositePK . Values . ToArray ( ) ) . FirstOrDefault ( ) ;
918
+ }
919
+ else
920
+ {
921
+ return Query < T > ( map . GetByPrimaryKeySql , pk ) . FirstOrDefault ( ) ;
922
+ }
872
923
}
873
924
874
925
/// <summary>
@@ -897,7 +948,7 @@ public T FindWithQuery<T>(string query, params object[] args) where T : class
897
948
/// the given type have a designated PrimaryKey (using the PrimaryKeyAttribute).
898
949
/// </summary>
899
950
/// <param name="pk">
900
- /// The primary key.
951
+ /// The primary key. Needs to be Dictionary<string, object> if table has composite PK.
901
952
/// </param>
902
953
/// <param name="map">
903
954
/// The TableMapping used to identify the object type.
@@ -909,7 +960,24 @@ public T FindWithQuery<T>(string query, params object[] args) where T : class
909
960
[ PublicAPI ]
910
961
public object Find ( object pk , TableMapping map )
911
962
{
912
- return Query ( map , map . GetByPrimaryKeySql , pk ) . FirstOrDefault ( ) ;
963
+ if ( map . HasCompositePK )
964
+ {
965
+ IDictionary < string , object > compositePK = pk as Dictionary < string , object > ;
966
+ if ( compositePK == null )
967
+ {
968
+ throw new NotSupportedException ( map . TableName + " table has a composite primary key. Make sure primary key is passed in as Dictionary<string, object>." ) ;
969
+ }
970
+ var cpk = map . CompositePK ;
971
+ if ( compositePK . Keys . Intersect ( cpk . Select ( p => p . Name ) ) . Count ( ) < cpk . Length )
972
+ {
973
+ throw new NotSupportedException ( "Cannot find in " + map . TableName + ": CompositePK mismatch. Make sure PK names are valid." ) ;
974
+ }
975
+ return Query ( map , map . GetByPrimaryKeySql , compositePK . Values . ToArray ( ) ) . FirstOrDefault ( ) ;
976
+ }
977
+ else
978
+ {
979
+ return Query ( map , map . GetByPrimaryKeySql , pk ) . FirstOrDefault ( ) ;
980
+ }
913
981
}
914
982
915
983
/// <summary>
@@ -1488,10 +1556,23 @@ public int Insert(object obj, string extra, Type objType)
1488
1556
}
1489
1557
1490
1558
var map = GetMapping ( objType ) ;
1559
+ TableMapping . Column pk = null ;
1491
1560
1492
- if ( map . PK != null && map . PK . IsAutoGuid )
1561
+ if ( map . HasCompositePK )
1493
1562
{
1494
- var prop = objType . GetRuntimeProperty ( map . PK . PropertyName ) ;
1563
+ pk = map . CompositePK . FirstOrDefault ( p => p . IsAutoGuid ) ;
1564
+ }
1565
+ else
1566
+ {
1567
+ if ( map . PK != null && map . PK . IsAutoGuid )
1568
+ {
1569
+ pk = map . PK ;
1570
+ }
1571
+ }
1572
+
1573
+ if ( pk != null )
1574
+ {
1575
+ var prop = objType . GetRuntimeProperty ( pk . PropertyName ) ;
1495
1576
if ( prop != null )
1496
1577
{
1497
1578
if ( prop . GetValue ( obj , null ) . Equals ( Guid . Empty ) )
@@ -1596,29 +1677,57 @@ public int Update(object obj, Type objType)
1596
1677
}
1597
1678
1598
1679
var map = GetMapping ( objType ) ;
1680
+ string q = null ;
1681
+ object [ ] ps = null ;
1682
+
1683
+ if ( map . HasCompositePK )
1684
+ {
1685
+ var compositePK = map . CompositePK ;
1686
+ var cols = from p in map . Columns
1687
+ where ! compositePK . Any ( pk => pk == p )
1688
+ select p ;
1689
+
1690
+ var pslist = ( from c in cols
1691
+ select c . GetValue ( obj ) ) . ToList ( ) ;
1692
+
1693
+ pslist . AddRange ( compositePK . Select ( pk => pk . GetValue ( obj ) ) ) ;
1599
1694
1600
- var pk = map . PK ;
1695
+ q = string . Format ( "update \" {0}\" set {1} where {2}" , map . TableName ,
1696
+ string . Join ( "," , ( from c in cols
1697
+ select "\" " + c . Name + "\" = ? " ) . ToArray ( ) ) , string . Join ( " and " , compositePK . Select ( pk => "\" " + pk . Name + "\" = ? " ) ) ) ;
1601
1698
1602
- if ( pk == null )
1699
+ ps = pslist . ToArray ( ) ;
1700
+ }
1701
+ else
1603
1702
{
1604
- throw new NotSupportedException ( "Cannot update " + map . TableName + ": it has no PK" ) ;
1703
+ var pk = map . PK ;
1704
+
1705
+ if ( pk == null )
1706
+ {
1707
+ throw new NotSupportedException ( "Cannot update " + map . TableName + ": it has no PK" ) ;
1708
+ }
1709
+
1710
+ var cols = from p in map . Columns
1711
+ where p != pk
1712
+ select p ;
1713
+
1714
+ var vals = from c in cols
1715
+ select c . GetValue ( obj ) ;
1716
+ var pslist = new List < object > ( vals )
1717
+ {
1718
+ pk . GetValue ( obj )
1719
+ } ;
1720
+
1721
+ q = string . Format ( "update \" {0}\" set {1} where {2} = ? " , map . TableName ,
1722
+ string . Join ( "," , ( from c in cols
1723
+ select "\" " + c . Name + "\" = ? " ) . ToArray ( ) ) , pk . Name ) ;
1724
+
1725
+ ps = pslist . ToArray ( ) ;
1605
1726
}
1606
1727
1607
- var cols = from p in map . Columns
1608
- where p != pk
1609
- select p ;
1610
- var vals = from c in cols
1611
- select c . GetValue ( obj ) ;
1612
- var ps = new List < object > ( vals )
1613
- {
1614
- pk . GetValue ( obj )
1615
- } ;
1616
- var q = string . Format ( "update \" {0}\" set {1} where {2} = ? " , map . TableName ,
1617
- string . Join ( "," , ( from c in cols
1618
- select "\" " + c . Name + "\" = ? " ) . ToArray ( ) ) , pk . Name ) ;
1619
1728
try
1620
1729
{
1621
- rowsAffected = Execute ( q , ps . ToArray ( ) ) ;
1730
+ rowsAffected = Execute ( q , ps ) ;
1622
1731
}
1623
1732
catch ( SQLiteException ex )
1624
1733
{
@@ -1680,20 +1789,35 @@ public int UpdateAll(IEnumerable objects, bool runInTransaction = true)
1680
1789
public int Delete ( object objectToDelete )
1681
1790
{
1682
1791
var map = GetMapping ( objectToDelete . GetType ( ) ) ;
1683
- var pk = map . PK ;
1684
- if ( pk == null )
1792
+ string q = null ;
1793
+ object [ ] ps = null ;
1794
+
1795
+ if ( map . HasCompositePK )
1796
+ {
1797
+ var compositePK = map . CompositePK ;
1798
+ q = string . Format ( "delete from \" {0}\" where {1}" , map . TableName , string . Join ( " and " , compositePK . Select ( pk => "\" " + pk . Name + "\" = ? " ) ) ) ;
1799
+ ps = ( from pk in compositePK
1800
+ select pk . GetValue ( objectToDelete ) ) . ToArray ( ) ;
1801
+ }
1802
+ else
1685
1803
{
1686
- throw new NotSupportedException ( "Cannot delete " + map . TableName + ": it has no PK" ) ;
1804
+ var pk = map . PK ;
1805
+ if ( pk == null )
1806
+ {
1807
+ throw new NotSupportedException ( "Cannot delete " + map . TableName + ": it has no PK" ) ;
1808
+ }
1809
+ q = string . Format ( "delete from \" {0}\" where \" {1}\" = ?" , map . TableName , pk . Name ) ;
1810
+ ps = new object [ ] { pk . GetValue ( objectToDelete ) } ;
1687
1811
}
1688
- var q = string . Format ( "delete from \" {0} \" where \" {1} \" = ?" , map . TableName , pk . Name ) ;
1689
- return Execute ( q , pk . GetValue ( objectToDelete ) ) ;
1812
+
1813
+ return Execute ( q , ps ) ;
1690
1814
}
1691
1815
1692
1816
/// <summary>
1693
1817
/// Deletes the object with the specified primary key.
1694
1818
/// </summary>
1695
1819
/// <param name="primaryKey">
1696
- /// The primary key of the object to delete.
1820
+ /// The primary key of the object to delete. Needs to be Dictionary<string, object> if table has composite PK.
1697
1821
/// </param>
1698
1822
/// <returns>
1699
1823
/// The number of objects deleted.
@@ -1705,13 +1829,34 @@ public int Delete(object objectToDelete)
1705
1829
public int Delete < T > ( object primaryKey )
1706
1830
{
1707
1831
var map = GetMapping ( typeof ( T ) ) ;
1708
- var pk = map . PK ;
1709
- if ( pk == null )
1832
+
1833
+ if ( map . HasCompositePK )
1710
1834
{
1711
- throw new NotSupportedException ( "Cannot delete " + map . TableName + ": it has no PK" ) ;
1835
+ var cpk = map . CompositePK ;
1836
+ IDictionary < string , object > compositePK = primaryKey as Dictionary < string , object > ;
1837
+ if ( compositePK == null )
1838
+ {
1839
+ throw new NotSupportedException ( map . TableName + " table has a composite primary key. Make sure primary key is passed in as Dictionary<string, object>." ) ;
1840
+ }
1841
+ if ( compositePK . Keys . Intersect ( cpk . Select ( p => p . Name ) ) . Count ( ) < cpk . Length )
1842
+ {
1843
+ throw new NotSupportedException ( "Cannot delete " + map . TableName + ": CompositePK mismatch. Make sure PK names are valid." ) ;
1844
+ }
1845
+ var q = string . Format ( "delete from \" {0}\" where {1}" , map . TableName , string . Join ( " and " , compositePK . Keys . Select ( pk => "\" " + pk + "\" = ? " ) ) ) ;
1846
+ var ps = ( from pk in compositePK . Values
1847
+ select pk ) . ToArray ( ) ;
1848
+ return Execute ( q , ps ) ;
1849
+ }
1850
+ else
1851
+ {
1852
+ var pk = map . PK ;
1853
+ if ( pk == null )
1854
+ {
1855
+ throw new NotSupportedException ( "Cannot delete " + map . TableName + ": it has no PK" ) ;
1856
+ }
1857
+ var q = string . Format ( "delete from \" {0}\" where \" {1}\" = ?" , map . TableName , pk . Name ) ;
1858
+ return Execute ( q , primaryKey ) ;
1712
1859
}
1713
- var q = string . Format ( "delete from \" {0}\" where \" {1}\" = ?" , map . TableName , pk . Name ) ;
1714
- return Execute ( q , primaryKey ) ;
1715
1860
}
1716
1861
1717
1862
/// <summary>
0 commit comments