簡體   English   中英

EF6代碼優先,多個級聯路徑和奇怪的FK行為

[英]EF6 Code First, multiple cascade paths, and strange FK behaviour

我將嘗試僅將模型的相關部分放在這里,因為有很多類。 希望足以解決問題:

public class Solve
{
    public int SolveID { get; set; }

    public int LocationID { get; set; }
    public virtual Location Location { get; set; }

    public int ProfileID { get; set; }
    public virtual Profile Profile { get; set; }

    public int BillID { get; set; }
    public virtual Bill Bill { get; set; }

    public int? PanelID { get; set; }
    public virtual Panel Panel { get; set; }
}

public class Location
{
    public int LocationID { get; set; }

    [Index]
    [StringLength(48)]
    public string Name  { get; set; }

    [Index]
    public State State { get; set; }

    public double Latitude  { get; set; }
    public double Longitude { get; set; }

    public virtual List<Profile> Profiles { get; set; }
}

public class Profile
{
    public int ProfileID { get; set; }

    public int LocationID { get; set; }
    public virtual Location Location { get; set; }

    public double Capacity { get; set; }

    public virtual List<ProfileSample> ProfileSamples { get; set; }
}

public class ProfileSample
{
    [Key, ForeignKey("Profile")]
    [Column(Order = 1)]
    public int ProfileID { get; set; }
    public virtual Profile Profile { get; set; }

    [Key]
    [Column(Order = 2)]
    [DataType(DataType.Date)]
    public DateTime Date { get; set; }

    [Key]
    [Column(Order = 3)]
    public TimeSpan TimeOfDay { get; set; }

    public double SampleValue { get; set; }
}

因此,在我介紹Solve類之前,一切都很好,這時它開始抱怨“多個級聯路徑”。 我在上下文中添加了以下內容,從那時起似乎還可以:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Solve>()
        .HasRequired(s => s.Location)
        .WithRequiredDependent()
        .WillCascadeOnDelete(false);
}

除非它的行為不正常:

using (Model.BlueData bd = new Model.BlueData())
{
    Random rng = new Random();

    s = new Model.Solve()
    {
        Location = bd.Locations.Find(rng.Next(0, bd.Locations.Count())),
        Bill     = bd.Bills.Find(rng.Next(0, bd.Bills.Count())),
        Profile  = bd.Profiles.Find(rng.Next(0, bd.Profiles.Count()))
    };

    bd.Solves.Add(s);
    bd.SaveChanges();

    s = bd.Solves
        .Where(u => u.SolveID == s.SolveID)
        .Include(u => u.Location)
        .Include(u => u.Profile)
        .Include(u => u.Profile.ProfileSamples)
        .Include(u => u.Bill)
        .FirstOrDefault();
}

因此,上面的代碼只是生成一個隨機的Solve對象,將其添加到數據上下文中,然后與所有關聯的數據一起再次檢索它。 當然,有一種更優雅的方法,但是現在這只是測試代碼,以確保我的應用程序的其他部分正常工作。

因此,正如預期的那樣,當我創建Solve s對象時, s.Location是一個特定的位置,ID為1609 ,當然s.LocationIDs.SolveID都等於0

將其添加到數據上下文並保存更改后, s.SolveID等於位置的ID(在此示例中為1609 )。 真奇怪 我嘗試在SolveSolveID [Key]屬性添加到SolveID並將[ForeignKey("Location")]LocationID ,但這沒有什么區別。

我嘗試了各種操作,例如從Solve刪除Profile或從Location中刪除List<Profile> Profiles 我現在不記得了,但是確實做了一些事情來更正s.SolveID設置為位置的ID行為。

但是這些屬性全部存在是有原因的,並且如果可能的話,我寧願不必為了使它正常工作而刪除它們。 我不明白為什么會這樣,或者如何正確糾正它。 感謝您的協助。

首先, Location是在Solve對象中引用的,所以位置是主體,而Solve是依賴的,我認為在這種情況下,這種映射是錯誤的-

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Solve>()
        .HasRequired(s => s.Location)
        .WithRequiredDependent()
        .WillCascadeOnDelete(false);
}

它應該是 -

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Solve>()
        .HasRequired(s => s.Location)
        .WillCascadeOnDelete(false);
}

其次,由於Solve了使用外鍵引用的問題,因此定義應為-

public class Solve
{
    public int SolveID { get; set; }

    [ForeignKey("Location")]
    public int LocationID { get; set; }
    public virtual Location Location { get; set; }

    [ForeignKey("Profile")]
    public int ProfileID { get; set; }
    public virtual Profile Profile { get; set; }

    [ForeignKey("Bill")]
    public int BillID { get; set; }
    public virtual Bill Bill { get; set; }

    [ForeignKey("Panel")]
    public int? PanelID { get; set; }
    public virtual Panel Panel { get; set; }
}

第三,在保存對象時,您必須首先保存1)主要對象,否則EF會嘗試創建新條目,或者2)您必須手動附加它們。 我發現的最簡單的方法是(1),保存完主端后,我僅分配了外鍵,並且EF正常工作。

using (Model.BlueData bd = new Model.BlueData())
{
    Random rng = new Random();

    s = new Model.Solve()
    {
        LocationID = bd.Locations.Find(rng.Next(0, bd.Locations.Count())).LocationID,
        BillID     = bd.Bills.Find(rng.Next(0, bd.Bills.Count())).BillID,
        ProfileID  = bd.Profiles.Find(rng.Next(0, bd.Profiles.Count())).ProfileID
    };
    s.Bill = s.Location = s.Profile = null; //otherwise EF tries to create them
    bd.Solves.Add(s);
    bd.SaveChanges();

    s = bd.Solves
        .Where(u => u.SolveID == s.SolveID)
        .Include(u => u.Location)
        .Include(u => u.Profile)
        .Include(u => u.Profile.ProfileSamples)
        .Include(u => u.Bill)
        .FirstOrDefault();
}

編輯1:位置類為-

public class Location
{
    [Key]  //mark location ID as primary key
    public int LocationID { get; set; }

    [Index]
    [StringLength(48)]
    public string Name  { get; set; }

    [Index]
    public State State { get; set; }

    public double Latitude  { get; set; }
    public double Longitude { get; set; }

    public virtual List<Profile> Profiles { get; set; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM