【问题标题】:Extending an Entity Framework property扩展实体框架属性
【发布时间】:2012-03-19 14:34:52
【问题描述】:

我有一个名为 File 的实体,我创建了一个带有属性的部分类。

我能够在常规构造函数和其他语句中使用此属性。但是这个属性在任何 linq 语句中都不被接受。

我收到以下异常。

例外

LINQ to Entities 不支持指定的类型成员“FileStatus”。仅支持初始化程序、实体成员和实体导航属性。

代码

var fileEntry = from entry in context.ICFiles
                             where entry.FileName == FileName &&
                                   entry.FileStatus == FileStatus.InProgress
                             select entry;

fileEntry.First().FileStatus = FileStatus.Completed; 
// This is where I get the exception

属性定义

public partial class ICFile
{
    [DataMemberAttribute()]
    public FileStatus FileStatus
    {
        get
        {
            return (FileStatus)this.Status;
        }
        set
        {
            this.Status = (int)value;
        }
    }
}

【问题讨论】:

  • 您是使用代码优先还是数据库优先与 edmx 文件或其他方法(可能是 T4 生成的代码)?我不认为你可以在实体框架中使用部分类,但如果有更多信息,也许有办法让它工作

标签: c# entity-framework


【解决方案1】:

我认为问题在于实体框架正在尝试将您的 FileStatus 属性转换为数据库中的一列,该列不存在并且没有映射信息可以继续,因为您在部分中定义了它班级。

我看到您正在尝试强制转换为枚举,因为大概您正在使用显然支持枚举的版本 5 beta 之前的实体框架版本(我可能错了,也许它仍然丢失)。

遗憾的是,枚举在当前的实体框架版本 (4.3.1) 中并不能很好地工作。你可以做各种各样的事情,但没有一个是非常令人满意的,你经常会意外地将整个表加载到内存中或者同样可怕的事情(参见Using ADO.net Entity Framework 4 with Enumerations? How do I do it?)。

为了简单起见,我个人不会打扰部分类并像这样进行查询:

var fileEntry = from entry in context.ICFiles
                         where entry.FileName == FileName &&
                               entry.Status == (int)FileStatus.InProgress
                         select entry;

fileEntry.First().Status = (int)FileStatus.Completed; 

不理想,但它有效,它显示了正在发生的事情,并且您知道 where 子句将被正确转换为等效的 SQL 位以针对数据库运行(我认为这称为“实用”)。

【讨论】:

    【解决方案2】:

    我认为您在代码示例中使用 Enums 的方式不会导致任何问题。问题很简单,EF 没有将您的类扩展属性识别为ICFiles 的成员,因为它既不在您的edmx 模型中,也不是您数据库表中的列。使用 user1039947 给你的代码示例,你应该没问题。

    但是,在对 ICFiles IEnumerable 实例执行 LINQ to Object 搜索时,您可以使用原始查询。这是因为 LINQ to Entities 在从数据库中获取数据之前被转换为 SQL,而 LINQ to 对象是在内存中完成的。您的 FileStatus 属性在您的数据库中不存在,仅在内存中。

    【讨论】:

    • 是的,从语法上讲它很好,如果它是对象 IEnumerable 的直接 linq,它会起作用,正如你所说,因为这将是一个内存查询。您可以重新构造查询以执行 where entry.FileName == FileName 部分,然后执行 ToList 例如,然后执行 where FileStatus == FileStatus.InProgress (因为对数据库的查询将在 ToList 发生)但是您最终会得到更复杂的代码,更糟糕的是,您拉回的内存比实际需要的多,这确实会损害性能。
    • @user1039947 我不是建议他这样做,我建议他按照你告诉他的去做。我是说枚举与他的问题无关,我不希望他对他得到异常的原因感到困惑。很明显,他必须从数据库中提取的数据量越少越好,但如果他已经在内存中拥有数据,那么他可以按照他最初打算的方式查询。他需要知道这一点,这样他才能明白什么时候可以应用什么。
    【解决方案3】:

    当我问这个问题时,我得到了@user1039947 发布的答案。但是,这不是我期望的这个问题的答案。

    我一直在寻找实体框架完全利用枚举的能力。但最终我发现 Linq to Entity 无法识别枚举(它通常通过以 Edm 开头的属性识别实体,如 EdmTypeAttribute、EntityPropertyAttribute 等)

    框架 4.0 的 Linq to Entity,无法接受枚举作为实体对象。然而,partial 方法为我们提供了 80% 我们可能需要的枚举。

    我已经发布了blog,其中包含更多详细信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多