澄清:我并没有尝试将类/类型存储在数据库字段中,或使用类/类型本身作为键值。我尝试使用类/类型的单个属性(在本例中为 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/