SQLite.Net InsertOrReplaceWithChildren 的扩展问题
SQLite.Net Extensions issue with InsertOrReplaceWithChildren
我正在使用 SQLite-Net PCL 和 SQLite-Net 扩展一起使用 Xamarin 开发应用程序。
我有两个类A
和B
定义如下:
public class A
{
[PrimaryKey, AutoIncrement]
public int Id
{
get;
set;
}
[Unique]
public string Name
{
get;
set;
}
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<B> Sons
{
get;
set;
}
public A(string name, List<B> sons)
{
Name = name;
Sons = sons;
}
}
public class B
{
[PrimaryKey, AutoIncrement]
public int Id
{
get;
set;
}
[Unique]
public string Name
{
get;
set;
}
public string LastModified
{
get;
set;
}
[ForeignKey(typeof(A))]
public int FatherId
{
get;
set;
}
[ManyToOne]
public A Father
{
get;
set;
}
public B()
{
}
public B(string name)
{
Name = name;
}
}
我正在尝试通过以下方式使用插入或替换:
var sons1 = new List<B>
{
new B("uno"),
};
var a1 = new A("padre", sons1);
var sons2 = new List<B>
{
new B("uno2"),
};
var a2 = new A("padre", sons2);
using (var conn = DatabaseStore.GetConnection())
{
conn.DeleteAll<A>();
conn.DeleteAll<B>();
}
using (var conn = DatabaseStore.GetConnection())
{
conn.InsertOrReplaceWithChildren(a1, true);
conn.InsertOrReplaceWithChildren(a2, true);
}
问题是第二个 InsertOrReplaceWithChildren
抛出 Constraint
异常,如果我们移除 A.Name
上的唯一约束,则不会抛出该异常。如果违反唯一约束,InsertOrReplaceWithChildren
不应该替换对象吗?
我检查了该行的提交,现在我想起来了:AutoIncrement
主键似乎只适用于 Insert
语句而不适用于 InsertOrReplace
。因此,如果您在 AutoIncrement
主键设置为 0 的情况下调用 InsertOrReplace
,它将始终覆盖 ID 为 0 的数据库中的相同值,而不是正确添加新值。
这个问题很容易通过执行这个测试来检查:
var a = new List<A> {
new A("a1", null),
new A("a2", null),
new A("a3", null),
new A("a4", null),
new A("a5", null),
new A("a6", null)
};
foreach (var element in a) {
conn.InsertOrReplace(element);
}
// Will fail expecting 6 elements but returning only 1
Assert.AreEqual(a.Count, conn.Table<A>().ToList().Count);
要解决它,您必须放弃 AutoIncrement
主键或 Unique
约束检查才能使 InsertOrReplace
语句起作用。
这些是直接替换 类,应该可以按预期工作,放弃 AutoIncrement
主键:
public class A
{
[PrimaryKey]
public Guid Id { get; set; }
[Unique]
public string Name { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<B> Sons { get; set; }
public A() {}
public A(string name, List<B> sons)
{
Id = Guid.NewGuid();
Name = name;
Sons = sons;
}
}
public class B
{
[PrimaryKey]
public Guid Id { get; set; }
[Unique]
public string Name { get; set; }
public string LastModified { get; set; }
[ForeignKey(typeof(A))]
public Guid FatherId { get; set; }
[ManyToOne]
public A Father { get; set; }
public B() {}
public B(string name)
{
Id = Guid.NewGuid();
Name = name;
}
}
希望对您有所帮助。
我正在使用 SQLite-Net PCL 和 SQLite-Net 扩展一起使用 Xamarin 开发应用程序。
我有两个类A
和B
定义如下:
public class A
{
[PrimaryKey, AutoIncrement]
public int Id
{
get;
set;
}
[Unique]
public string Name
{
get;
set;
}
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<B> Sons
{
get;
set;
}
public A(string name, List<B> sons)
{
Name = name;
Sons = sons;
}
}
public class B
{
[PrimaryKey, AutoIncrement]
public int Id
{
get;
set;
}
[Unique]
public string Name
{
get;
set;
}
public string LastModified
{
get;
set;
}
[ForeignKey(typeof(A))]
public int FatherId
{
get;
set;
}
[ManyToOne]
public A Father
{
get;
set;
}
public B()
{
}
public B(string name)
{
Name = name;
}
}
我正在尝试通过以下方式使用插入或替换:
var sons1 = new List<B>
{
new B("uno"),
};
var a1 = new A("padre", sons1);
var sons2 = new List<B>
{
new B("uno2"),
};
var a2 = new A("padre", sons2);
using (var conn = DatabaseStore.GetConnection())
{
conn.DeleteAll<A>();
conn.DeleteAll<B>();
}
using (var conn = DatabaseStore.GetConnection())
{
conn.InsertOrReplaceWithChildren(a1, true);
conn.InsertOrReplaceWithChildren(a2, true);
}
问题是第二个 InsertOrReplaceWithChildren
抛出 Constraint
异常,如果我们移除 A.Name
上的唯一约束,则不会抛出该异常。如果违反唯一约束,InsertOrReplaceWithChildren
不应该替换对象吗?
我检查了该行的提交,现在我想起来了:AutoIncrement
主键似乎只适用于 Insert
语句而不适用于 InsertOrReplace
。因此,如果您在 AutoIncrement
主键设置为 0 的情况下调用 InsertOrReplace
,它将始终覆盖 ID 为 0 的数据库中的相同值,而不是正确添加新值。
这个问题很容易通过执行这个测试来检查:
var a = new List<A> {
new A("a1", null),
new A("a2", null),
new A("a3", null),
new A("a4", null),
new A("a5", null),
new A("a6", null)
};
foreach (var element in a) {
conn.InsertOrReplace(element);
}
// Will fail expecting 6 elements but returning only 1
Assert.AreEqual(a.Count, conn.Table<A>().ToList().Count);
要解决它,您必须放弃 AutoIncrement
主键或 Unique
约束检查才能使 InsertOrReplace
语句起作用。
这些是直接替换 类,应该可以按预期工作,放弃 AutoIncrement
主键:
public class A
{
[PrimaryKey]
public Guid Id { get; set; }
[Unique]
public string Name { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<B> Sons { get; set; }
public A() {}
public A(string name, List<B> sons)
{
Id = Guid.NewGuid();
Name = name;
Sons = sons;
}
}
public class B
{
[PrimaryKey]
public Guid Id { get; set; }
[Unique]
public string Name { get; set; }
public string LastModified { get; set; }
[ForeignKey(typeof(A))]
public Guid FatherId { get; set; }
[ManyToOne]
public A Father { get; set; }
public B() {}
public B(string name)
{
Id = Guid.NewGuid();
Name = name;
}
}
希望对您有所帮助。