C# 如何拦截EF操作?
我目前正在为一个项目使用实体框架,我的一个类有一个表示一些值的枚举 到目前为止,EF将枚举保存为数据库中的数字,但我希望将它们保存为实际的字符串名。例如,枚举NY保存为1,而不是“NY”C# 如何拦截EF操作?,c#,sql,string,entity-framework,enums,C#,Sql,String,Entity Framework,Enums,我目前正在为一个项目使用实体框架,我的一个类有一个表示一些值的枚举 到目前为止,EF将枚举保存为数据库中的数字,但我希望将它们保存为实际的字符串名。例如,枚举NY保存为1,而不是“NY” 我已经看到了一些实现这一点的方法,比如使用一个带有隐藏Enum私有字段的string属性,但我想知道是否有一种方法可以在EF执行CRUD操作时截获EF,然后在数据上下文类中将Enum更改为字符串 否,您不能直接这样做:当您使用Enum属性映射类时,该属性映射到数据库int列,并且您不能以任何方式更改它。我的意思
我已经看到了一些实现这一点的方法,比如使用一个带有隐藏Enum私有字段的string属性,但我想知道是否有一种方法可以在EF执行CRUD操作时截获EF,然后在数据上下文类中将Enum更改为字符串 否,您不能直接这样做:当您使用
Enum
属性映射类时,该属性映射到数据库int
列,并且您不能以任何方式更改它。我的意思是,由于您无法更改模型,因此无法截取Enum
属性值并将其转换为字符串,因为模型顽固地想要int
也就是说,有几种方法可以让它发挥作用:
- 具有键的字符串属性和更新该键的
[NotMapped]
属性。请参阅注释:但是密钥必须是公共的,因此可以通过应用程序代码访问Enum
- 使用仅具有enum属性且在应用程序域中使用的类,以及用于EF模型的不同类,并映射值,例如使用
或valueinjector
Automapper
Enum
值定义字符串键,因此您可以在需要执行此操作的所有情况下重用此模式
注意:答案的这一部分是错误的:您可以映射修饰符的任何属性重新标记(public
,protected
,private
,internal
…)。EF约定仅包括public
属性,并且没有可以克服此限制的数据注释。但您可以将其与Fluent API一起使用。但是,由于该属性是私有的,因此无法使用Fluent API直接访问它。这里介绍了几种解决方案:
如果遵循此路径,则可以创建如下类:
public class MyEntity
{
// ...
[NotMapped]
public EnumType Value
{
get { /* return KeyForEnum converted to EnumType value */ }
set { /* set KeyForEnum value from the received EnumType value*/}
}
// Use some mechanism to map this private property
private string KeyForEnum { get; set; }
// ...
}
如您所见,如果您使用这样的类,则在应用程序中,实体将具有EnumType
type的属性,但在数据库中它将是一个字符串
通过Fluent API映射它的技巧之一是:
1) 添加一个静态属性,该属性返回一个能够从此类的对象中选择属性的表达式,即
public static readonly Expression<Func<MyEntity,string>> KeyForEnumExpression
= me => me.KeyForEnum;
最后注意:这将通过添加静态只读属性来修改POCO类。您可以使用反射来构建一个表达式来访问私有属性,如下所示:。它是西班牙语的,但是你可以直接看代码我认为这不是一个值得解决的问题。代理键在性能和可维护性方面都具有优势。你知道州的缩写在20世纪60年代发生了变化吗?另外,如果增加了更多的城市怎么办?我认为数据库中的名字比依赖于我的代码版本的一些随机数可读性好得多。要解决DB中的可读性问题:1。意见2。这就是为什么要使用查找表作为代码,这就是为什么要首先使用枚举。很抱歉,如果您使用的是EF,您的应用程序已经直接链接到数据库;这会引起很多问题!至于只有三个值,如果一个非常有限的值从正确的DB设计中排除,为什么不硬编码呢?它只有三个值…如果它保证它自己的表,它保证它自己的整数主键。不管它是实体还是查找。另外,您会惊讶地发现查找变成实体的频率有多高。
modelBuilder
.Entity()
.Property(MyEntity.KeyForEnumExpression)