我正在将现有的应用程序从Linq移植到SQL到Entity Framework 4(默认代码生成)。
我注意到两者之间的一个区别是重置对象引用时不会更新外键属性。现在我需要决定如何处理这个问题。
例如,假设您有两种实体类型,Company和Employee。一家公司有很多员工。
在Linq To SQL中,设置公司还会设置公司ID:
var company=new Company(ID=1);
var employee=new Employee();
Debug.Assert(employee.CompanyID==0);
employee.Company=company;
Debug.Assert(employee.CompanyID==1); //Works fine!
在实体框架中(并且不使用任何代码模板自定义),这不起作用:
var company=new Company(ID=1);
var employee=new Employee();
Debug.Assert(employee.CompanyID==0);
employee.Company=company;
Debug.Assert(employee.CompanyID==1); //Throws, since CompanyID was not updated!
如何使EF的行为与LinqToSQL相同?我看了默认代码生成T4模板,但我无法弄清楚如何进行必要的更改。看起来像一个单行应该可以做到这一点,但我无法弄清楚如何获得给定引用的ID属性。
答案 0 :(得分:4)
根据我在默认T4模板中看到的,实体的外键属性不直接链接到与密钥关联的实体引用。
Theres夫妇可以解决从Linq到SQL迁移到EF4的问题。其中之一是注册您的关联的AssociationChanged
事件,以便它自动更新您的字段。在您的上下文中,一种方法可能是这样的:
// Extends Employee entity
public partial class Employee
{
private void CompanyChanged(Object sender, CollectionChangeEventArgs e)
{
// Apply reactive changes; aka set CompanyID
// here
}
// Create a default constructor that registers your event handler
public Employee()
{
this.CompanyReference.AssociationChanged += CompanyChanged;
}
}
就个人而言,如果您想限制维护此类逻辑所需的维护,我建议您更改T4模板(自行更改或找到一个),以便在{CompanyId
时设置Company
1}}如前所示进行了更改。
Gil Fink为使用EF4的T4模板写了一篇很好的介绍,你可以查看Scott Hanselman包含大量有用的链接和资源来使用T4模板。
最后一点,除非我弄错了,直接访问外键作为实体的属性是从EF3.5到4的新内容。在3.5中,只有通过相关实体才能访问它({{ 1}})。我相信这个功能是在EF4中添加的,这样你就不必加载关联(使用“include”),以便在从数据存储中选择时获取外键。
也许EF对此的看法是,如果你有了这个关联,那么首先要通过协会来获取ID。但这只是猜测,因为我没有引用它来支持它。
[编辑2010-06-16] : 在对edmx xml元素进行快速阅读和分析之后,我发现了一个名为ReferentialConstraint的内容,它似乎包含指定FK_Relation的外键字段。
下面是修改默认T4 edmx模板内部的代码片段,编写导航属性部分。 (Employee.Company.CompanyID
),在未修改的模板的第388行附近。试着忽略可怕的格式......
Template_RegionNavigationProperties
我粗略测试了它,但它是一个给定的一些验证和这样的缺失。也许无论如何,它都可以为您提供解决方案。
答案 1 :(得分:2)
感谢您提供此解决方案。我已经增强了它(不再依赖于特定的命名约定),并且还包含在一个修复程序中,该修复程序还修复了Entity Framework模板的其他问题。
Check here for my solution and fixed code generation template