EF Core添加相關實體(通用存儲庫)

c# entity-framework-core uwp

我有一個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;
            }

我得到以下異常

拋出異常:Microsoft.EntityFrameworkCore.dll中的“Microsoft.EntityFrameworkCore.DbUpdateException”DbService插入異常:Microsoft.EntityFrameworkCore.DbUpdateException:更新條目時發生錯誤。有關詳細信息,請參閱內部異常---> Microsoft.Data.Sqlite.SqliteException:SQLite錯誤19:'UNIQUE約束失敗:AttributeTypes.AttributeTypeId'。 at Microsoft.Data.Sqlite.Interop.MarshalEx.ThrowExceptionForRC(Int32 rc,Sqlite3Handle db)at Microsoft.Data.SqliteCommand.ExecuteReader(CommandBehavior behavior)at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection,String 2 parameterValues, Boolean closeConnection) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary 2 parameterValues)中的executeMethod,IReadOnlyDictionary 2 parameterValues, Boolean closeConnection) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary )---內部異常結束堆棧跟踪---在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList)上的Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(元組2 parameters) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList IRelationalConnection連接) Mic的1個條目.ToSave)位於UwpSamples.Services.DbService.Insert [T](T item)的Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)的rosoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)

但是如果我沒有傳遞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);

謝謝

一般承認的答案

您正在實例化兩個單獨的上下文。您檢索AttributeType的位置,執行插入的存儲庫中的第二個上下文將遍歷實體並認為AttributeType是新的並嘗試插入它。我建議每個請求使用一個Context(假設這是Web請求的後面)。有一些解決方法涉及將實體標記為未更改,但您必須每次都重複解決方法,並且它對每個模型都非常具體。

通常,您使用Container或IoC框架來檢索每個請求的Context,或者您將在存儲庫的構造函數中傳遞上下文。這樣,您可以跨不同的存儲庫進行多次調用,並且更改跟踪將在調用之間起作用。它還簡化了跨越對不同存儲庫的調用打開事務範圍的方案。


熱門答案

根據失敗,attributeType.AttributeTypeId的值已經存在於DB中。你能檢查一下這個值是什麼嗎?它確實是唯一的嗎?我想這個值必須是唯一的,因為你將它用作主鍵。

如果未設置值或明確將其設置為null,則DB將自動生成ID,這解釋了它的工作原理。

希望能幫助到你。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow