gpt4 book ai didi

linq-to-sql - Entity Framework : Auto-updating foreign key when setting a new object reference

转载 作者:行者123 更新时间:2023-12-03 07:40:30 25 4
gpt4 key购买 nike

我正在将现有应用程序从 Linq to SQL 移植到 Entity Framework 4(默认代码生成)。

我注意到两者之间的一个区别是重置对象引用时不会更新外键属性。现在我需要决定如何处理这个问题。

例如,假设您有两种实体类型:公司和员工。一家公司有多名员工。

在 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!

在 Entity Framework 中(并且不使用任何代码模板自定义),这不起作用:

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 属性。

最佳答案

从我在默认 T4 模板中看到的情况来看,实体的外键属性并不直接链接到与该键关联的实体引用。

有几种方法可以解决您有关从 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 模板(您自己更改或找到一个),以便它设置 CompanyIdCompany 发生更改(如前所示)时。

Gil Fink写了一篇相当不错的关于T4模板与EF4的介绍,大家可以查一下Scott Hanselman包含大量有用的链接和资源以使用 T4 模板。

最后一点,除非我弄错了,否则直接访问外键作为实体的属性是从 EF3.5 到 4 的新内容。在 3.5 中,访问它的唯一方法是通过关联的实体(员工.公司.公司ID)。我相信 EF4 中添加了该功能,因此您在从数据存储中进行选择时无需加载关联(使用“include”)即可获取外键。

也许 EF 对此的看法是,如果你有关联,首先通过关联获取 ID。但这只是猜测,因为我没有任何报价来支持它。

[编辑2010-06-16]:在快速通读和分析 edmx xml 元素后,我发现了一个名为 ReferentialConstraint 的元素,它似乎包含特定 FK_Relation 的外键字段。

这是要在默认 T4 edmx 模板内修改的代码片段,写入导航属性部分。 (Template_RegionNavigationProperties),位于未修改模板的第 388 行左右。尝试忽略可怕的格式...

<#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> <#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#> <#=code.Escape(navProperty)#>
{
<#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value;
}
<#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
{
// edit begins here
if(value != null)
{
// Automatically sets the foreign key attributes according to linked entity

<#
AssociationType association = GetSourceSchemaTypes<AssociationType>().FirstOrDefault(_ => _.FullName == navProperty.RelationshipType.FullName);
foreach(var cons in association.ReferentialConstraints)
{
foreach(var metadataProperty in cons.FromProperties)
{
#>
this.<#=metadataProperty.Name#> = value.<#=metadataProperty.Name#>;
//this._<#=metadataProperty.Name#> = value._<#=metadataProperty.Name#>; // use private field to bypass the OnChanged events, property validation and the likes..

<#
}
}
#>
}
else
{
// what usually happens in Linq-to-SQL when an association is set to null
// here
}
// edit ends here

((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value = value;
}
}

我粗略地测试了它,但肯定存在一些验证和缺失。也许它可以为您提供解决方案的提示。

关于linq-to-sql - Entity Framework : Auto-updating foreign key when setting a new object reference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3023993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com