实体框架6 - 将主键作为类型的属性

时间:2015-10-30 18:42:41

标签: c# .net entity-framework

澄清:我没有尝试将类/类型存储在数据库字段中,或者使用类/类型本身作为键值。我试图使用Class / Type的单个属性(在本例中为Guid)作为键。

虽然我认为它与此特定问题严格相关,但它可能对上下文有用:我正在尝试在我的最新项目中实施Semantic Types。我在整个代码中取得了一些成功,事实上已经确定了一些可能不会很快被识别出来的错误。

在一些Fluent API代码的帮助下,一切都很好地将我的语义类型与EF6集成在非键字段中。

但是,当尝试对键字段使用语义类型时,EF会生成一个运行时异常,说明没有定义键 - 显然有。

使用简单的Guid作为键

以下是我使用的不使用语义类型的EF实体的示例:

public partial class MyEntity
{
    [Key]
    public Guid id { get; set; }

    public string SomeData { get; set; }
}

以上工作正常。

将Type属性作为键 - 尝试#1

现在,我定义了一个新的语义类型,如下所示:

public class MyEntityId: SemanticType<Guid>
{
    public MyEntityId()
        : base(IsValid, Guid.Empty)
    { }

    public MyEntityId(Guid value)
        : base(IsValid, value)
    { }

    public static bool IsValid(Guid value)
    {
        return true;
    }
}

...并相应地更新EF模型。

public partial class MyEntity
{
    [Key]
    public MyEntityId id { get; set; }

    public string SomeData { get; set; }
}

然后我将一些代码添加到DbContext OnModelCreating方法,以将MyEntityId.Value映射到所需的列名:

modelBuilder
  .Entity<MyEntity>()
    .Property(x => x.MyEntityId.Value)
    .HasColumnName("id");

现在,以上所有编译都很好。但是只要与表进行交互,我就会得到以下异常:

An exception of type 'System.Data.Entity.ModelConfiguration.ModelValidationException'
occurred in EntityFramework.dll but was not handled in user code

EntityType 'MyEntity' has no key defined. Define the key for this MyEntity.

显然,实体确实有一个键定义。

将Type属性作为键 - 尝试#2

所以,我尝试从模型中删除[key]属性,并修改了Fluent API代码,如下所示:

modelBuilder
  .Entity<MyEntity>()
    .HasKey(x => x.MyEntityId.Value);
    .Property(x => x.MyEntityId.Value)
    .HasColumnName("id")

但是这段代码会产生以下异常:

An exception of type 'System.InvalidOperationException' occurred in
EntityFramework.dll but was not handled in user code

Additional information: The properties expression 'x => x.MyEntityId.Value'
is not valid. The expression should represent a property: 
C#: 't => t.MyProperty'  VB.Net: 'Function(t) t.MyProperty'. 
When specifying multiple properties use an anonymous type: 
C#: 't => new { t.MyProperty1, t.MyProperty2 }'
VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.

将Type属性作为键 - 尝试#3

因此,在挖掘SO之后,看起来EF需要一个属性,而不仅仅是一个公共领域。所以我修改了语义类型来引入一个新的&#34; EFValue&#34;财产,如下:

public class MyEntityId: SemanticType<Guid>
{
    public MyEntityId()
        : base(IsValid, Guid.Empty)
    { }

    public MyEntityId(Guid value)
        : base(IsValid, value)
    { }

    public static bool IsValid(Guid value)
    {
        return true;
    }

    public Guid EFValue
    {
        get { return Value; }
    }
}

...并修改了Fluent API代码,如下所示:

modelBuilder
  .Entity<MyEntity>()
    .HasKey(x => x.MyEntityId.EFValue);
    .Property(x => x.MyEntityId.Value)
    .HasColumnName("id")

然后我得到了相同的&#39; System.InvalidOperationException&#39;异常。

是否无法在EF6中将此类型的属性定义为主键?

1 个答案:

答案 0 :(得分:1)

错误很明显,你无法做你想做的事。只需在实体级别包装ID属性,它就可以工作:

public partial class MyEntity
{
    public MyEntityId BadIdea { get; set; }

    [Key]
    public Guid Id 
    { 
       get 
       { 
            // needs null check
            return BadIdea.Value; 
       } 
       set 
       { 
           // needs null check
           BadIdea.Value = value; 
       }
    }
}
相关问题