【问题标题】:Entity Framework: Ignore Columns实体框架:忽略列
【发布时间】:2021-03-01 00:13:39
【问题描述】:

我有一个希望从中构建 EF 模型的数据库,但我不想包含数据库中的某些列,因为相关列仅在服务器上维护,不应由任何应用程序操作。

两列都是 DateTime(如果这有什么不同的话),其中一列可以为空并由更新触发器维护,另一列不可为空并使用表定义中的默认值进行设置。

我想我正在寻找类似于 Linq2Sql 中的“服务器生成”选项的东西;但我找不到这样的选择。

谁能告诉我如何解决这个问题?

警告:

多年来,我一直试图在我的工作场所引入业务对象建模,但由于需要手动操作的额外代码量,它总是被拒绝。由于设计器和代码生成,EF 目前被视为一种可行的解决方案,因此任何涉及手动启动 XML 的选项只会让我的其他同事远离 EF。因此,我正在寻找可以使用设计器或代码来完成的事情。

编辑:

我想我在这里寻找的是……

(a) 一种在没有 EF 引用存储中的列 (ssdl) 的情况下创建模型的方法,因此不希望以任何方式对其进行操作 (b) 一种在创建 ObjectContext 时以编程方式针对该属性设置“StoreGeneratedPattern”属性的方法(简单的答案是在 .ssdl 中手动操作它,但如果我从数据库中刷新模型和我不能沿着 .csdl、.msl 和 .ssdl 手摇的路线走)。

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    你能用实体框架做到这一点吗?是的;这很简单。你能用实体框架设计器做到这一点吗?不幸的是,这要困难得多。

    您遇到的问题是该列存在于 EDMX 的存储架构 (SSDL) 中。使用 GUI 设计器删除列只是将其从客户端模式中删除,而不是从映射或存储模式中删除。但是,进入 EDMX 并删除它很简单。完成此操作后,您还可以将其从 EDMX 客户端模式部分的映射中删除,实体框架将不再抱怨它未映射。

    问题解决了,对吧?

    嗯,不。当您使用 GUI 设计器从数据库更新 EDMX 时,存储模式将被丢弃并重新生成。所以你的专栏会回来。据我所知,没有办法告诉 GUI 设计者永远不要映射特定的列。因此,每次使用 GUI 设计器更新时,您都必须重新执行此操作。幸运的是,EDMX 是 XML,因此您可以使用 XML 转换、LINQ 或您选择的 XML 工具来执行此操作。

    【讨论】:

    • 谢谢,我有点意识到我可以通过编辑 XML 来做到这一点,我只是希望有另一种方法 - 例如在创建上下文时以编程方式设置 StoreGeneratedPattern 属性。
    • 嗯,答案是一样的(对于 StoreGeneratedPattern)。您可以在 XML 中设置 StoreGeneratedPattern,它会正常工作,但 GUI 设计器会在您更新时将其吹走。实体框架具有 GUI 设计器尚未完全支持的功能。
    • 唯一的其他选择是尝试更改您的数据库元数据,以便 GUI 设计器识别您想要的内容。但是不知道在StoreGeneratedPattern的具体情况下GUI设计器是如何生成SSDL的。
    • 我知道这个问题很古老,但是您可以创建一个控制台应用程序来在重新生成后修改您的 edmx。我已经为一些设计师无法处理的定制任务完成了这项工作。因此,我们的部分流程是在您更新并保存 edmx 之后,您运行控制台应用程序,然后在您的模型 tt 文件上“运行自定义工具”以重新生成模型。我们使用 Visual Studio 的 Task Runner Explorer 和 Mads Kristensen 的 Command Task Runner 扩展来使其易于运行。
    【解决方案2】:

    你不能用你需要的列创建一个视图并通过实体函数向导将它导入并映射到你的实体吗?

    【讨论】:

    • 谢谢,这可能是一个解决方案,但如果可以的话,我宁愿避免为每个表创建视图 - 我在原始问题中描述的列实际上出现在数据库中的每个表上.
    【解决方案3】:

    您可以修改文本模板以在生成实体类时忽略这些列。例如,如果您在文档摘要中添加了“IGNORE”,则可以修改模板以通过替换来忽略它们;

    Dim simpleProperties as IEnumerable(Of EdmProperty) = typeMapper.GetSimpleProperties(entity)
    

    与;

    Dim simpleProperties as IEnumerable(Of EdmProperty) = typeMapper.GetSimpleProperties(entity).Where(Function(p) p.Documentation is nothing orelse p.Documentation.Summary.IndexOf("IGNORE")<0)
    

    【讨论】:

      【解决方案4】:

      右键单击图形表示中的字段并选择删除。我发现有时当您一次对建模进行大量更改并开始忘记更改时会出错。您最好的选择可能是重建 EF 生成的模型。

      请记住,当您“从数据库更新”时,生成的模型上的旧字段不会被删除,您必须手动删除它们。例如,如果您在数据库中将 DateField1 重命名为 DateField2,然后“从数据库更新模型”,您现在将在结果模型上看到 DateField1 和 DateField2。这可能会导致错误。

      【讨论】:

      • 这适用于可为空的列,但不适用于不可为空的列,产生与上述 TGnat 选项相同的错误。
      • 错误 3023:从第 197 行开始映射片段时出现问题:必须映射表 TableName 中的列 TableName.ColumnName:它没有默认值且不可为空。
      • 我知道了...我想你可能被卡住了。有趣的注意事项...我的一个数据库表上有一个 rowversion (timestamp) 列,并且 EF 生成器正确设置了 StoreGeneratedPattern 属性:
      • 有趣;我想知道 TimeStamp 列有什么不同可以做到这一点?
      • TimeStamp 用于并发检查,当行中的某些内容发生变化时,SQL Server 会自动更新它。这就是为什么 EF 会将其识别为不同的东西。
      【解决方案5】:

      您根本不希望该列出现在模型中吗?

      尝试在设计器视图中选择列并点击删除键。

      编辑

      您可以将属性的设置器设为私有。那么您的应用将无法修改该值。

      【讨论】:

      • 不幸的是,如果我尝试这样做,我会在模型中出现错误,因为列未映射。
      • 错误 3023:从第 197 行开始映射片段时出现问题:必须映射表 TableName 中的列 TableName.ColumnName:它没有默认值且不可为空。
      • 操作 setter 的问题是模型仍然知道该列存在,因此尝试在插入时传递该类型的默认值 - 对于 DateTime,这是 SQL Server 之外的值范围并覆盖默认值。
      • Property Getter 和 Setter 设置为 Private,谢谢
      【解决方案6】:

      Timestamp 是与 DateTime 不同的数据类型。时间戳似乎被认为是引擎管理的属性,很像身份属性。您不能“更新”时间戳属性。因此,EDM 可以正确管理它(就像它管理身份一样)。

      【讨论】:

        【解决方案7】:

        在 EDMX 设计器中,选择属性并将 StoreGeneratedPattern 设置为 Computed。

        【讨论】:

          猜你喜欢
          • 2014-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-29
          • 2016-06-05
          相关资源
          最近更新 更多