1

我将尝试仅将模型的相关部分放在这里,因为有相当多的类。希望这足以捕捉问题:EF6代码首先,多个级联路径和奇怪的FK行为

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)。这很奇怪。我尝试在Solve类中添加[Key]属性到SolveID[ForeignKey("Location")]LocationID,但它没有区别。

我尝试了各种方法,如从Solve中删除Profile或从位置中删除List<Profile> Profiles。我现在不记得了,但有几件事情可以纠正设置为位置ID行为的s.SolveID

但是,这些属性都是有原因的,如果可能的话,我宁愿不删除它们只是为了得到这个工作。我不明白为什么会发生这种情况,或者如何正确纠正。我很感激任何帮助。

+0

我认为,外键将需要重新添加,醚作为数据annotion(你已经tried-,我还以为是解决方案)或者可能使用流利的API来添加它。这也许可以解决它:http://stackoverflow.com/questions/21229373/ef-foreign-key-using-fluent-api –

回答

2

首先Location被在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:Location类是 -

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; } 
} 
+0

非常感谢你的答案。这一行:'s.Bill = s.Location = s.Profile = null;',是否有必要?你说否则EF会尝试创建它们,但它们应该已经是'null'了,对吧? – Ozzah

+0

是的,但这只是为了确保它们是空的。你不会在任何地方都有相同的代码。如果它解决了你的问题,请接受答案,以便有相同问题的其他人知道这可能是一个解决方案。 –

+0

我实施了您推荐的更改,现在出现错误:Solve_Location_Source :: Multiplicity在“Solve_Location”关系中的'Solve_Location_Source'角色中无效。因为“依赖角色”属性不是关键属性,所以“依赖角色”的多重性的上界必须为“*”。 – Ozzah