dec*_*yte 8 c# modeling code-first entity-framework-4.1
我现在花了几天时间,试图解决这个问题.在制作一个简单的项目来举例说明我的问题时,我偶然发现了一个可能的解决方案.所以,这是一个双重问题.
但首先,一些背景信息:
我刚开始使用Entity Framework 4.1(EF)和Code First为我的ASP.NET MVC项目创建模型.我需要一些类似的模型:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TestApp.Models
{
public class Family
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Father> Fathers { get; set; }
public virtual ICollection<Mother> Mothers { get; set; }
}
public class Mother
{
public int ID { get; set; }
public string Name { get; set; }
public int FamilyID { get; set; }
public virtual ICollection<Child> Children { get; set; }
public virtual Family Family { get; set; }
}
public class Father
{
public int ID { get; set; }
public string Name { get; set; }
public int FamilyID { get; set; }
public virtual ICollection<Child> Children { get; set; }
public virtual Family Family { get; set; }
}
public class Child
{
public int ID { get; set; }
public string Name { get; set; }
public int MotherID { get; set; }
public int FatherID { get; set; }
public virtual Mother Mother { get; set; }
public virtual Father Father { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
和DbContext:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace TestApp.Models
{
public class TestContext : DbContext
{
public DbSet<Family> Families { get; set; }
public DbSet<Mother> Mothers { get; set; }
public DbSet<Father> Fathers { get; set; }
public DbSet<Child> Children { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
(请原谅这个蹩脚的例子,那是我星期五油炸大脑能够想到的.)
一个家庭可以有几个母亲和几个父亲.一个孩子有一个母亲和一个父亲.我在我的工作中检查过一位.NET专家,他们同意这一点没有什么特别之处.至少就我们所见.
但是当我运行代码时,我得到了这个例外:
System.Data.SqlServerCe.SqlCeException:引用关系将导致不允许循环引用.[约束名称= Mother_Family]
我确实看到了这个循环:Family - Mother - Child - Father - Family.但是,如果我自己创建数据库表(我不喜欢,这就是我喜欢的Code First),就我所知,它将是一个完全有效的数据结构.
所以,我的第一个问题是:为什么在首先使用代码时这是一个问题?有没有办法告诉EF如何正确处理循环?
然后,正如我最初写的那样,在创建一个简单的项目来举例说明我的问题时,我偶然发现了一个可能的解决方案.我在定义模型时忘记了一些属性.为了清楚起见,在下面的示例中,我没有删除它们,而是注释掉了我忘记的模型部分:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TestApp.Models
{
public class Family
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Father> Fathers { get; set; }
public virtual ICollection<Mother> Mothers { get; set; }
}
public class Mother
{
public int ID { get; set; }
public string Name { get; set; }
// public int FamilyID { get; set; }
public virtual ICollection<Child> Children { get; set; }
public virtual Family Family { get; set; }
}
public class Father
{
public int ID { get; set; }
public string Name { get; set; }
// public int FamilyID { get; set; }
public virtual ICollection<Child> Children { get; set; }
public virtual Family Family { get; set; }
}
public class Child
{
public int ID { get; set; }
public string Name { get; set; }
// public int MotherID { get; set; }
// public int FatherID { get; set; }
public virtual Mother Mother { get; set; }
public virtual Father Father { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
因此,删除这些SomethingID引用属性似乎解决了我的问题.正如你在本文最后链接到的示例项目的控制器中所看到的那样,我仍然能够一路循环并做一些mothers.First().Family.Fathers.First().Children.First().Mother.Family.Name没有任何问题的东西.但是我所关注的EF和Code First建模的所有教程和示例(例如Scott Guthrie的这个)都包含这些属性,因此不使用它们感觉不对.
所以,我的第二个问题是:我还没有发现任何缺点和问题吗?
在此处下载示例项目:http://blackfin.cannedtuna.org/cyclical-reference-test-app.zip,并打开TestSolution.sln.这些属性在示例项目中被注释掉.取消注释TestModels.cs中的行以添加属性,从而导致循环引用异常.
注意:解决方案是创建并播种位于c:\ TestApp.sdf的SQL CE数据库
更新,2011年12月: 我从未在技术上解决过这个问题,但我辞掉了工作,找到了另一份工作,我不必使用Microsoft技术.那种解决了我的问题:)
由于旧地方的技术支持在修复问题时曾经写过:"提供了一种解决方法或解决方案".
这是一个已知问题,您并不是第一个遇到它的人。据我所知,他们正在即将推出的 WCF 版本中开发更好的解决方案,但目前根据我的经验,您最好创建代表要通过线路发送的数据的 DataContracts,从而更改数据结构删除循环引用。
我知道这很痛苦,但是还有其他好处,因为您很可能希望对客户端使用的结构进行其他更改,而不是让他们使用数据库中存在的对象