实体框架(Entity Framework):忽略列

35

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

这两个列都是DateTime(如果这有什么区别的话),其中一个列是可空的,并通过更新触发器维护,另一个列是非空的,并在表定义中使用默认值设置。

我猜我正在寻找像Linq2Sql中的“Server Generated”选项一样的东西;但我找不到这样的选项。

有人能告诉我如何解决这个问题吗?

注意:

我一直在尝试在我的工作场所引入业务对象建模多年,但由于必须手动编写大量额外的代码而一直被拒绝。EF目前被看作是一个可行的解决方案,因为它具有设计器和代码生成功能,因此,任何涉及手动编写XML的选项都只会让我的同事对EF产生反感。因此,我正在寻找一些可以使用设计器或代码完成的东西。

编辑:

我想我在这里要找的是...

(a)创建模型的方法,使EF不引用存储(ssdl)中的列,因此不会以任何方式操作它
(b)在创建ObjectContext时以编程方式设置“StoreGeneratedPattern”属性的方法(简单的答案是手动在 .ssdl 中操作这个,但如果我从数据库刷新模型,它将被覆盖,我不能走手工编写 .csdl、.msl 和 .ssdl 的路线)。

7个回答

30

你能用Entity Framework(实体框架)来做这个吗?可以,很容易。你能用Entity Framework设计器来做这个吗?不幸的是,那要难得多。

你遇到的问题是列在EDMX的存储模式(SSDL)中存在。使用GUI设计器删除列只会从客户端模式移除它,而不会从映射或存储模式中移除。然而,进入EDMX并删除它非常简单。这样做后,你还可以从EDMX的客户端模式部分的映射中删除它,这样实体框架就不会再抱怨它未映射。

问题解决了,对吧?

嗯,不完全是。当你使用GUI设计器从数据库更新EDMX时,存储模式会被丢弃并重新生成。所以你的列会重新出现。据我所知,没有办法告诉GUI设计器永远不要映射特定的列。因此,每次使用GUI设计器更新时都需要重新进行处理。幸运的是,EDMX是XML格式,因此你可以使用XML转换、LINQ或你选择的XML工具来处理。


1
谢谢,我有点意识到我可以通过编辑XML来实现这一点,我只是希望还有另一种方法 - 比如在创建上下文时以编程方式设置StoreGeneratedPattern属性。 - Martin Robins
1
好的,StoreGeneratedPattern 的答案是一样的。您可以在 XML 中设置 StoreGeneratedPattern,它将正常工作,但当您更新时,GUI 设计器会将其清除。Entity Framework 具有 GUI 设计器尚未完全支持的功能。 - Craig Stuntz
唯一的其他选择是尝试更改数据库元数据,以便GUI设计师识别您想要的内容。但我不知道GUI设计师在StoreGeneratedPattern的特定情况下如何生成SSDL。 - Craig Stuntz
我知道这个问题古老了,但你可以创建一个控制台应用程序,在它重新生成后修改你的edmx。我已经为一些设计师无法处理的定制任务完成了这项工作。因此,我们的流程的一部分就是在更新和保存edmx之后,运行控制台应用程序,然后在模型tt文件上“运行自定义工具”来重新生成模型。我们使用Visual Studio的任务运行器浏览器与Mads Kristensen的命令任务运行器扩展,使其易于运行。 - xr280xr

2
你能否通过实体函数向导创建所需列的视图并将其映射到你的实体中,而不是编写解释代码?请保留HTML标签。

2
谢谢,这可能是一个解决方案,尽管如果可以的话,我更愿意避免为每个表创建视图 - 我在原始问题中描述的列实际上出现在数据库中的每个表中。 - Martin Robins

1

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

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

with;

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

1
你不想在模型中看到这一列吗?
尝试在设计视图中选择该列,然后按删除键。
编辑
你可以将属性的setter设置为私有。这样,你的应用程序就无法修改该值了。

5
很遗憾,如果我尝试这样做,模型会出错,因为该列未被映射。 - Martin Robins
错误 3023:映射片段出现问题,起始行为197行:表格 TableName 中的列 TableName.ColumnName 必须进行映射:它没有默认值且不可为空。 - Martin Robins
操作setter的问题在于,模型仍然知道该列存在,因此尝试在插入时传递类型的默认值 - 对于DateTime类型,这是超出SQL Server范围的值,它会覆盖默认值。 - Martin Robins
1
属性的Getter和Setter设置为私有对我很有帮助,谢谢。 - Diego

0

时间戳是一种不同于日期时间的数据类型。时间戳似乎被认为是引擎管理的属性,就像标识属性一样。您无法“更新”时间戳属性。因此,EDM可以正确地管理它(就像它处理标识一样)。


0

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

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


这个适用于可空列,但对于不可空列无效,会产生与TGnat上述选项相同的错误。 - Martin Robins
错误3023:映射片段问题从第197行开始:表TableName中的列TableName.ColumnName必须被映射:它没有默认值且不可为空。 - Martin Robins
我明白了...我想你可能卡住了。有趣的是,我的一个数据库表上有一个rowversion(时间戳)列,EF生成器正确地设置了StoreGeneratedPattern属性:<Property Name="RowVer" Type="timestamp" Nullable="false" StoreGeneratedPattern="Computed" />。 - John B
有趣;我想知道TimeStamp列有什么不同,以使其能够做到这一点? - Martin Robins
TimeStamp 用于并发检查,当行中的数据发生更改时,SQL Server 会自动更新它。这就是为什么 EF 会将其识别为不同的东西。 - Koob

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接