2016-07-03 34 views
0

我們銷售的產品爲其頒發許可證編號,並且客戶可以每年進行升級。我想設置一個License POCO,通過定義UpgradedToUpgradedFrom導航屬性來跟蹤此升級信息,這將允許我們輕鬆地上下移動相關許可證的「鏈」。所以基本上是這樣的:多個自引用導航屬性

public class License 
{ 
    [Key] 
    public string LicenseNum { get; set; } 
    // Other properties relating to license omitted... 

    // Optional relationship. 
    public License UpgradedTo { get; set; } 

    // Optional relationship. 
    public License UpgradedFrom { get; set; } 
} 

我真的很掙扎如何定義這與EF批註和Fluent API。我認爲自我參照方面是讓我絆倒的東西。

我們也希望能夠設置在任一給License這些UpgradeTo/UpgradeFrom特性之一,有EF在關係的另一端走「相反的」升級屬性的照顧。所以像下面這樣:

// Licenses upgraded 1 > 2 > 3 
License lic1 = CreateLicense('1'); 
License lic2 = CreateLicense('2'); 
License lic3 = CreateLicense('3'); 

using (var db = new Model1()) 
{ 
    // Insert into database 
    db.Licenses.Add(lic1); 
    db.Licenses.Add(lic2); 
    db.Licenses.Add(lic3); 
    db.SaveChanges(); 

    // Specify UpgradeFrom/UpgradeTo info only on lic2. 
    lic2.UpgradedFrom = lic1; 
    lic2.UpgradedTo = lic3; 
    db.SaveChanges(); 

    // lic1 and lic3 automatically update possible? 
    Debug.Assert(lic1.UpgradedTo == lic2); 
    Debug.Assert(lic3.UpgradedFrom == lic2); 
} 

回答

0

這種情況是非常棘手的,因爲依賴如何工作。

訣竅是添加一個或多個額外的「假」屬性來完成這項工作。

如果您設置了UpgradeTo值,該類將自動設置UpgradedFrom屬性。

例子:

using (var ctx = new TestContext2()) 
{ 
    var license1 = ctx.Licenses.Add(new License() { LicenseNum = "1.0.0"}); 
    ctx.SaveChanges(); 

    var license2 = license1.UpgradeTo = new License() { LicenseNum = "1.0.2"}; 
    ctx.SaveChanges(); 

    var license3 = license2.UpgradeTo = new License() { LicenseNum = "1.0.3" }; 
    ctx.SaveChanges(); 
} 

實體

public class License 
{ 
    [Key] 
    public string LicenseNum { get; set; } 

    private License _upgradeTo; 
    private License _upgradedFrom; 


    public License UpgradeTo 
    { 
     get { return _upgradeTo; } 
     set 
     { 
      _upgradeTo = value; 
      if (_upgradeTo != null && _upgradeTo.UpgradedFrom != this) 
      { 
       _upgradeTo.UpgradedFrom = this; 
      } 
     } 
    } 

    public License UpgradedFrom 
    { 
     get { return _upgradedFrom; } 
     set 
     { 
      _upgradedFrom = value; 
      if (_upgradedFrom != null && _upgradedFrom.UpgradeTo != this) 
      { 
       _upgradedFrom.UpgradeTo = this; 
      } 
     } 
    } 

    internal License InternalUpgradedTo 
    { 
     get { return UpgradeTo; } 
    } 

    internal License InternalUpgradedFrom 
    { 
     get { return UpgradedFrom; } 
    } 
} 

語境

public class TestContext2 : DbContext 
{ 
    public TestContext2() : base(My.Config.ConnectionStrings.TestDatabase) 
    { 

    } 
    public DbSet<License> Licenses { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<License>() 
      .HasOptional(v => v.UpgradeTo) 
      .WithOptionalDependent(x => x.InternalUpgradedFrom); 

     modelBuilder.Entity<License>() 
      .HasOptional(v => v.UpgradedFrom) 
      .WithOptionalDependent(x => x.InternalUpgradedTo); 
    } 
} 
+0

這種方法完美的作品。非常感謝! – John