我有一个具有以下模型和一对多关系的EF Core Db
public class AttributeType
{
public int AttributeTypeId { get; set; }
public string Name { get; set; }
public List<Attribute> AttributeList { get; set; }
}
public class Attribute
{
public int AttributeId { get; set; }
public string Name { get; set; }
public int AttributeTypeId { get; set; }
public AttributeType AttributeType { get; set; }
}
如果我尝试以这种方式添加属性,它可以工作:
using (var db = new SampleDbContext())
{
var attributeType = db.AttributeTypes.FirstOrDefault();
Attribute attribute = new Attribute
{
Name = "bbb",
AttributeTypeId = attributeType.AttributeTypeId,
AttributeType = attributeType
};
var item = db.Attributes.Add(attribute);
db.SaveChanges();
}
(实际上,attributeType将来自组合框和文本框中的名称,但现在让我们保持代码简单)
但是当我尝试使用泛型方法时,如下面的代码,不起作用
AttributeType attributeType;
using (var db = new SampleDbContext())
{
attributeType = db.AttributeTypes.FirstOrDefault();
}
Attribute attribute = new Attribute
{
Name = "eee",
AttributeType = attributeType,
AttributeTypeId = attributeType.AttributeTypeId
};
DbService.Insert(attribute);
public static bool Insert<T>(T item) where T : class
{
try
{
using (var db = new SampleDbContext())
{
db.Add(item);
db.SaveChanges();
}
return true;
}
catch (Exception exception)
{
Debug.WriteLine($"DbService Insert Exception: {exception}");
return false;
}
我得到以下异常
抛出异常:&#39; Microsoft.EntityFrameworkCore.DbUpdateException&#39;在Microsoft.EntityFrameworkCore.dll中 DbService插入异常:Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时发生错误。有关详细信息,请参阅内部异常---&GT; Microsoft.Data.Sqlite.SqliteException:SQLite错误19:&#39; UNIQUE约束失败:AttributeTypes.AttributeTypeId&#39;。 在Microsoft.Data.Sqlite.Interop.MarshalEx.ThrowExceptionForRC(Int32 rc,Sqlite3Handle db) 在Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior行为) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection,String executeMethod,IReadOnlyDictionary
2 parameterValues, Boolean closeConnection) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary
2 parameterValues) 在Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection连接) ---内部异常堆栈跟踪结束--- 在Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection连接) 在Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(元组2 parameters) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList
1 entriesToSave) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess) 在Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess) 在UwpSamples.Services.DbService.Insert [T](T item)
但是如果我没有传递AttributeType或者我将它设置为null,就像下面的代码一样,它可以工作:
AttributeType attributeType;
using (var db = new SampleDbContext())
{
attributeType = db.AttributeTypes.FirstOrDefault();
}
Attribute attribute = new Attribute
{
Name = "ddd",
AttributeType = null,
AttributeTypeId = attributeType.AttributeTypeId
};
DbService.Insert(attribute);
-
AttributeType attributeType;
using (var db = new SampleDbContext())
{
attributeType = db.AttributeTypes.FirstOrDefault();
}
Attribute attribute = new Attribute
{
Name = "ddd",
AttributeTypeId = attributeType.AttributeTypeId
};
DbService.Insert(attribute);
由于
答案 0 :(得分:2)
您正在实例化两个单独的上下文。您检索AttributeType的位置,执行插入的存储库中的第二个上下文将遍历实体并认为AttributeType是新的并尝试插入它。我建议每个请求使用一个Context(假设这是Web请求的后面)。有一些解决方法可能会将实体标记为未更改,但您每次都必须重复解决方法,并且每个模型都非常具体。
通常您使用Container或IoC框架来检索每个请求的Context,或者您在存储库的构造函数中传递上下文。这样,您可以跨不同的存储库进行多次调用,并且更改跟踪将在调用之间起作用。它还简化了在不同存储库的调用之间打开事务范围的情况。
答案 1 :(得分:1)
根据失败,attributeType.AttributeTypeId的值已经存在于DB中。你能检查一下这个值是什么吗?它确实是唯一的吗? 我想这个值必须是唯一的,因为你将它用作主键。
当您未设置值或明确将其设置为null时,数据库会自动生成ID,这解释了它的工作原理。
希望它有所帮助。