首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架6-将主键作为类型的属性

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

Stack Overflow用户
提问于 2015-10-30 18:42:40
回答 1查看 1.9K关注 0票数 2

澄清:我不打算将类/类型存储在数据库字段中,也不打算使用类/类型本身作为键值。我试图使用类/类型的单个属性(在本例中为Guid)作为键。

虽然我认为它与这个特定的问题没有严格的关联,但它可能对上下文很有用:我正在尝试在我的最新项目中实现语义类型。在我的代码中,我已经取得了一些成功,事实上,我发现了一些错误,它们可能不会很快被识别出来。

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

但是,当试图为密钥字段使用语义类型时,EF会生成一个运行时异常,说明没有定义键--如果确实存在。

以简单Guid作为密钥的

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

代码语言:javascript
复制
public partial class MyEntity
{
    [Key]
    public Guid id { get; set; }

    public string SomeData { get; set; }
}

上面的效果很好。

具有类型属性的作为密钥尝试#1

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

代码语言:javascript
复制
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模型。

代码语言:javascript
复制
public partial class MyEntity
{
    [Key]
    public MyEntityId id { get; set; }

    public string SomeData { get; set; }
}

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

代码语言:javascript
复制
modelBuilder
  .Entity<MyEntity>()
    .Property(x => x.MyEntityId.Value)
    .HasColumnName("id");

现在,以上所有内容都可以很好地编译。但是,一旦与表进行交互,我就会得到以下例外:

代码语言:javascript
复制
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.

显然,实体确实有一个已定义的密钥。

具有类型属性的作为密钥尝试#2

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

代码语言:javascript
复制
modelBuilder
  .Entity<MyEntity>()
    .HasKey(x => x.MyEntityId.Value);
    .Property(x => x.MyEntityId.Value)
    .HasColumnName("id")

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

代码语言:javascript
复制
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 }'.

具有类型属性的作为密钥尝试#3

因此,在挖掘So之后,EF似乎需要一个属性,而不仅仅是一个公共领域。因此,我修改了语义类型,引入了一个新的"EFValue“属性,如下所示:

代码语言:javascript
复制
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代码,如下所示:

代码语言:javascript
复制
modelBuilder
  .Entity<MyEntity>()
    .HasKey(x => x.MyEntityId.EFValue);
    .Property(x => x.MyEntityId.Value)
    .HasColumnName("id")

但是,我得到了同样的“System.InvalidOperationException”例外。

不能将这样的类型的属性定义为EF6?中的主键

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-02 17:09:54

这个错误非常清楚地表明,你不能做你想做的事。只需在实体级别包装ID属性,它就能工作:

代码语言:javascript
复制
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; 
       }
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33442875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档