具有收集和导航到特定元素的 EF 模型

EF Model with collection and navigation to a particular element

如何使用模型 class 配置 EF6 迁移?

public class MyModel
{
    [Key]
    public int Id { get; set; }

    // My collection of elements
    public virtual ICollection<MyCollectionElement> MyCollection { get; set; }

    // Optional navigation to a particular element from the collection
    [ForeignKey("CurrentElement")]
    public int? CurrentElementId { get; set; }

    public virtual MyCollectionElement CurrentElement { get; set; }
}

public class MyCollectionElement
{
    [Key]
    public int Id { get; set; }

    // Required navigation to MyClass
    [ForeignKey("MyModel")]
    public int MyModelID { get; set; }

    public virtual MyModel Model { get; set; }
}

配置

modelBuilder.Entity<MyModel>()
    .HasMany(x => x.MyCollection)
    .WithRequired(x => x.Model)
    .HasForeignKey(x => x.MyModelID)
    .WillCascadadeOnDelete(false);

Update-Database 上抛出几个错误,比如

无法确定相关操作的有效排序。

我想要一个不涉及 MyCollectionElement 中的 boolean IsCurrent 的解决方案,以便稍后进行另一个查询并找到哪个元素是当前元素;相反,我想用我的模型存储当前元素的 id,比如 exposed。

另外,我不介意让 int CurrentElementId 不可为空(需要),如果这样更容易的话。

谢谢。

当存在循环关系时,这个先有鸡还是先有蛋的问题总是迫在眉睫。错误...

Unable to determine a valid ordering for dependent operations.

...创建数据库时不会抛出。可以很好地创建数据库。当您尝试在同一工作单元中插入相互引用的 MyModel 记录和 MyCollectionElement 时,就会发生这种情况。在 Seed 方法中你可能有类似

的东西
var element = new MyCollectionElement();
var model = new MyModel();
model.MyCollection.Add(element);
model.CurrentElement = element;

语句model.MyCollection.Add(element);需要先插入model,所以element可以在它的外键中引用它。但是 model.CurrentElement = element; 需要先插入 element

您只能通过调用 SaveChanges 两次来避免这种情况,如果您希望分配是事务性的,则将所有内容包装在 TransactionScope 中:

using(var ts = new TransactionScope())
{    
    using(var db = new MyContext()
    {
        var element = new MyCollectionElement();
        var model = new MyModel();
        model.MyCollection.Add(element);
        db.MyModels.Add(model);
        db.SaveChanges();

        model.CurrentElement = element;
        db.SaveChanges();
    }
    ts.Complete();
}

这也意味着 int CurrentElementId 应该保持为空。