实体框架6自定义关系公约

时间:2013-03-23 19:13:29

标签: c# entity-framework entity-framework-6

我已阅读有关实体框架6中的约定的this文档。但它不包含关系约定。

假设我有以下模型:

[TablePrefix("mst")]
public class Guru
{
    public int Id { get; set; }

    public int? IdKotaLahir { get; set; }

    public virtual Kota KotaLahir { get; set; }
}

我希望属性IdKotaLahir是导航属性KotaLahir的外键。 外键名称为"Id"+<NavigationPropertyName>。 是否可以使用当前版本的实体框架(EF 6 alpha 3)?

2 个答案:

答案 0 :(得分:2)

它只是一个属性还是你需要全面的(即整个模型使用的是外键名称总是“Id”+ NavigationPropertyName)的约定?如果您只想要单个实体的外键,那么最好只使用ForeignKey属性:

public class Guru
{
    public int Id { get; set; }

    public int? IdKotaLahir { get; set; }

    [ForeignKey("IdKotaLahir")]
    public virtual Kota KotaLahir { get; set; }
}

这适用于EF5和EF6。在EF6中,您可以使用自定义约定来配置外键属性。这是我提出的自定义约定:

public class NavigationPropertyConfigurationConvention
    : IConfigurationConvention<PropertyInfo, NavigationPropertyConfiguration>
{
    public void Apply(
        PropertyInfo propertyInfo, Func<NavigationPropertyConfiguration> configuration)
    {
        var foreignKeyProperty = 
            propertyInfo.DeclaringType.GetProperty("Id" + propertyInfo.Name);

        if (foreignKeyProperty != null && configuration().Constraint == null)
        {
            var fkConstraint = new ForeignKeyConstraintConfiguration();
            fkConstraint.AddColumn(foreignKeyProperty);

            configuration().Constraint = fkConstraint;
        }           
    }
}

我还写了一篇更详细的blog post

答案 1 :(得分:2)

在EF6中,接受的答案的约定不再有效,因为IConfigurationConvention是内部的。处理此类场景的方法是继承ForeignKeyDiscoveryConvention。

public class MyForeignKeyDiscoveryConvention : ForeignKeyDiscoveryConvention
{
    protected override bool MatchDependentKeyProperty(AssociationType associationType, AssociationEndMember dependentAssociationEnd,
        EdmProperty dependentProperty, EntityType principalEntityType, EdmProperty principalKeyProperty)
    {
        string navigationPropertyName = ((System.Reflection.PropertyInfo)dependentAssociationEnd.MetadataProperties.GetValue("ClrPropertyInfo", false).Value).Name;

        // The standard foreign key property to look for is NavigationProperty_PrimaryKeyName (e.g. "TableName_Id"). 
        // Use the below line to remove that underscore.
        //return dependentProperty.Name == navigationPropertyName + principalKeyProperty.Name;

        // Use the following for the IdKotaLahir scenario
        return dependentProperty.Name == "Id" + navigationPropertyName;
    }
}