我正在嘗試使用Entity Framework 7更新外鍵。但是它給出了錯誤:在對象'X'中找不到屬性'Y'。我嘗試了很多不同的解決方案,但仍然沒有工作。示例代碼:

class X
{
  property Y {get; set;} -> property Y is a foreign key and also a complex type
}

在表'X'中,我們有一個'Y_ID'列,它是外鍵。

注意:我只想更新外鍵。例如, 最初類'X'指向'NULL'我想更新類'X'指向'Y1'

實體框架7代碼:

var x = this.GetX();
this.mainContext.Xs.Attach(x);
var xEntry = this.mainContext.Entry(x);

xEntry.Property("Y").CurrentValue = "Y1"; // Error at this line

await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

詳細錯誤:

無法找到實體類型“X”上的屬性“Y”。確保該屬性存在且已包含在模型中。

編輯

Fabien在他的評論中提出的方法很好。但問題是我們只知道要在運行時更新哪個屬性。如果我使用反射來實現這一點,問題是實體框架將對象視為新對象並嘗試創建它(INSERT)然後拋出主鍵衝突(不允許重複條目)

那麼,有沒有一種方法我仍然無法更新在EF中像外鍵一樣的對象屬性? (我在編譯時不知道確切的屬性)。

熱門答案

如果從上下文中獲取實體“X”和“Y”,則ChangeTracker會自動跟踪它們。因此,如果您將“X”對象的“Y”屬性與從上下文中檢索到的“Y”實例分配並調用SaveChanges或SaveChangesAsync,則EntityFramework將自動為您執行這些操作。

var x = this.GetX();    
x.Y = "Y1";
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

按照慣例,對象“X”上的屬性“Y”應該是虛擬的,表示它是外鍵。


編輯1:

如果我理解正確,您希望在運行時動態更新對象的屬性,其值應來自web api。

第一種方式:

與您一樣,您可以將“X”對象附加到上下文實例以開始使用EntityState.Unchanged跟踪實體,然後標記需要更新的每個屬性:

this.mainContext.Xs.Attach(x);
var entry = this.mainContext.entry(x);
entry.Property(p => p.Y).CurrentValue = "Y1";
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

附加實體時,您可以指定GraphBehavior,它告訴EntityFramework是否應該遍歷導航屬性。

第二種方式:

使用DbSet.Update()方法:

this.mainContext.Xs.Update(x);
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

它會自動開始跟踪狀態為EntityState.Modified的實體,所有屬性都將標記為已修改。您應該注意何時使用此方法,因為所有屬性都將更新,如果其中一些屬性未在“X”對像中初始化,則可能會丟失一些數據。為了防止這種情況,您應該始終驗證輸入。


如果您希望將您的域模型從任何ORM中解除耦合,那麼您應該考慮將實體類型和域類型分開。您可以使用像Automapper這樣的對象映射將實體映射到域類型,反之亦然。通過這種方式,您可以清楚地分離您在數據訪問層和業務邏輯層中所做的工作。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因