1

這種循環依賴在我的應用程序,一個Agency有許多Employees,其中之一是委託表示機構的擁有者:如何解決在EF

public class Employee 
{ 
    public int EmployeeId { get; set; } 
    public string EmployeeName { get; set; } 
    public int EmployerId { get; set; } 

    [ForeignKey("EmployerId")] 
    public virtual Agency Employer { get; set; } 
} 

public class Agency 
{ 
    public int AgencyId { get; set; } 
    public string AgencyName { get; set; } 
    public int OwnerId { get; set; } 

    [ForeignKey("OwnerId")] 
    public virtual Employee Owner { get; set; } 

    [InverseProperty("Employer")] 
    public virtual ICollection<Employee> Employees { get; set; } 
} 

我嘗試使用進入一個新的Agency到DATEBASE此代碼:

var agency = new Agency(); 
// ... 

context.Agencies.Add(agency); 

var owner = new Employee(); 
// ... 

context.Employees.Add(owner); 

owner.Employer = agency; 
agency.Owner = owner; 

context.SaveChanges(); 

當我打電話SaveChanges,我收到以下錯誤,我假設是由於循環依賴我如上所述:

無法確定依賴操作的有效順序。 由於外鍵約束, 需求或商店生成的值,可能會存在依存關係。

在EF中是否有方法來指定「依賴操作」的順序?或者,有沒有更好的方式來編寫我的數據庫,以便它能解決這個問題,但仍然模擬我想要的數據結構?

+0

不實際的數據庫架構看起來像你期待什麼呢? –

+0

是的,正是我期待的。 – ajbeaven

回答

3

我不確定是否可以在SQL中創建代理和所有者,因爲存儲代理需要有效的FK給所有者,並將所需的所有者存儲到代理所需的有效FK。由於FK約束(除非它們不會被強制執行),您不能在不違反約束的情況下存儲其中的任何約束。

溶液(我不知道另一個)被定義OwnerId可爲空使得可選的關係之一,例如Owner

public int? OwnerId { get; set; } 

這不會解決「有效立即訂購「異常,但現在您可以存儲沒有所有者的代理機構,然後將所有者存儲爲與已存儲代理機構的關係。爲了使整個操作「原子」可以換到SaveChanges兩個必要的調用到一個外部事務:

using (var tx = new TransactionScope()) 
{ 
    var agency = new Agency(); 

    context.Agencies.Add(agency); 

    context.SaveChanges(); // inner transaction 1 
    // saves agency with OwnerId = NULL, it wouldn't work with a required owner 
    // agency has a primary key from the database now 

    var owner = new Employee(); 

    context.Employees.Add(owner); 

    owner.Employer = agency; // sets FK EmployerId to the now known PK of agency 
    agency.Owner = owner; 

    context.SaveChanges(); // inner transaction 2 

    tx.Complete(); // commits the outer transaction 
} 
+0

嗯,傷心。我試圖避免一個事務,因爲我讀它們可能導致與實體框架的死鎖。上面的代碼是否可能導致任何此類問題? – ajbeaven

+1

@ajbeaven:是的,'TransactionScope'的* default *隔離級別相當有限('Serializable')。但是你可以很容易地改變它,例如,「快照」使得死鎖的可能性大大降低:http://blogs.msdn.com/b/diego/archive/2012/04/01/tips-to-avoid-deadlocks-在實體框架,applications.aspx – Slauma