c# - Entity Framework 6 - 将主键作为类型的属性

标签 c# .net entity-framework

澄清:我并没有尝试将类/类型存储在数据库字段中,或使用类/类型本身作为键值。我尝试使用类/类型的单个属性(在本例中为 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 需要一个属性,而不仅仅是一个公共(public)字段。因此我修改了语义类型以引入新的“EFValue”属性,如下所示:

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")

但随后我得到了相同的“System.InvalidOperationException”异常。

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

最佳答案

该错误清楚地表明您无法执行您想要的操作。只需在实体级别包装 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; 
       }
    }
}

关于c# - Entity Framework 6 - 将主键作为类型的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33442875/

相关文章:

c# - 如何在 C# 中制作音频流? (一般的)

c# - 标签透明底色

entity-framework - 如何在 ASP.NET 5 模板中添加实体数据模型

c# - 是什么导致 Linq 错误 : This method cannot be translated into a store expression?

c# - 在 C# 中使用 Youtube API V3 从 channel 获取视频

c# - 是否可以保证枚举的 ToString 的值是多少?

c# - 如何确定 .NET 中 explorer.exe 的路径?

c# - 如何从 C# 获取 Word 文档的文件名?

.net - 为什么在调试时 Word 会卡住?

c# - EF 中索引数据注释的错误消息