【问题标题】:How to Intercept EF operations?如何拦截 EF 操作?
【发布时间】:2015-03-18 18:54:22
【问题描述】:

我目前正在为一个项目使用实体框架,我的一个类有一个 Enum 代表一些值。

到目前为止,EF 将枚举保存为数据库中的数字,但我想将它们保存为它们的实际字符串名称。例如,枚举 NY 保存为 1,而不是“NY”。

我已经看到了一些方法来完成这项工作,比如拥有一个带有隐藏 Enum 私有字段的字符串属性,但我想知道是否有一种方法可以在执行 CRUD 操作时拦截 EF,然后我可以在 Data Context 类中将 Enum 更改为 String。

【问题讨论】:

  • 我认为这不是一个值得解决的问题。代理键在性能和可维护性方面都非常出色。您知道州缩写在 1960 年代发生了变化吗?另外,如果添加其他城市怎么办?
  • 我认为数据库中的名称比依赖于我的代码版本的一些随机数更具可读性。
  • 解决数据库中的可读性问题: 1. 视图 2. 这就是你有查找表的原因 至于代码,这就是你首先使用枚举的原因。抱歉,如果您使用的是 EF,那么您的应用已经直接链接到您的数据库。
  • 我目前正在研究一个以这种方式做事的遗留数据库;它会导致很多问题!至于只有三个值,如果一个非常有限的值可以作为适当的数据库设计的借口,为什么不对其进行硬编码呢?只有三个值...
  • 如果它保证它自己的表它保证它自己的整数主键。它是实体还是查找都没有关系。此外,您会惊讶于查找变成实体的频率。

标签: c# sql string entity-framework enums


【解决方案1】:

不,您不能直接这样做:当您使用Enum 属性映射您的类时,该属性将映射到数据库int 列,您无法以任何方式更改它。我的意思是,由于您无法更改模型,因此无法拦截Enum属性值并将其转换为字符串,因为模型固执地想要int

也就是说,有几种方法可以使它工作:

  • 具有键的字符串属性和更新该键的[NotMapped] Enum 属性。 查看注释:但密钥必须是公开的,因此可以通过应用程序代码访问。
  • 使用仅具有枚举属性并在您的应用程序域中使用的类,以及用于您的 EF 模型的不同类,并映射值,例如使用 ValueInjecterAutomapper

我通常采用第一个路径并使用允许我为每个 Enum 值定义字符串键的属性,因此您可以在需要这样做的所有情况下重用此模式。

注意:这部分答案是错误的:您可以映射任何与修饰符有关的属性(publicprotectedprivateinternal...)。 EF 约定仅包括public 属性,并且没有可以克服此限制的数据注释。但是您可以将它与 Fluent API 一起使用。但是,由于该属性是私有的,因此您无法使用 Fluent API 直接访问它。这里描述了几种解决方案:Code First Data Annotations on non-public properties

如果你走这条路,你可以有这样的课程:

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 类型的属性,但在数据库中它将是一个字符串。

能够通过 Fluent API 进行映射的技巧之一是:

1) 添加一个静态属性,该属性返回一个能够从该类的对象中选择属性的表达式,即

public static readonly Expression<Func<MyEntity,string>> KeyForEnumExpression
   = me => me.KeyForEnum;

2) 在 fluent API 中使用它来获取映射的属性,如下所示:

modelBuilder
  .Entity()
  .Property(MyEntity.KeyForEnumExpression)

最后注意:这将通过添加静态只读属性来修改 POCO 类。您可以改用反射来构建一个表达式来访问私有属性,就像您可以在此处看到的那样:EF 4.1 Code First, ¿map private members?。是西班牙语的,不过可以直接看代码

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 2019-03-27
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多