[英]Multiple self-referencing naviation properties
我們出售一種產品,我們為其頒發許可證號,並且客戶可以每年進行升級。 我想設置一個License
POCO,它通過定義UpgradedTo
和UpgradedFrom
導航屬性來跟蹤此升級信息,這將使我們能夠輕松地上下移動相關許可證的“鏈”。 所以基本上是這樣的:
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負責關系另一端的“相反” Upgrade屬性。 因此,如下所示:
// 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);
}
這種情況非常棘手,因為依賴性是如何工作的。
訣竅是添加一個或多個其他“偽”屬性來完成這項工作。
如果您設置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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.