【问题标题】:adding new methods to LINQ to Entities向 LINQ to Entities 添加新方法
【发布时间】:2013-07-01 09:47:27
【问题描述】:

有没有办法为 Linq2Entities 的附加功能定义 SQL 转换组件。

例如:

myQuery.Where(entity => entity.Contains('foo', SearchFlags.All))

理想情况下,我正在寻找不需要直接编辑和构建新版本 EntityFramework.dll 的东西。有没有办法允许扩展方法到可以支持 SQL 生成的实体框架。

到目前为止,我有一个模板可以代表我需要为 LINQ to Entities 替换的方法:

public static bool Contains(this object source, string searchTerms, SearchFlags flags)
{
    return true;
}

当然这会导致错误:

LINQ to Entities 无法识别“Boolean”方法 CONTAINS(System.Object, System.String, SearchFlags)' 方法和这个方法 无法翻译成商店表达式。

明确地说,我不想这样做:

myQuery.AsEnumerable().Where(entity => entity.Contains('foo', SearchFlags.All))

因为我希望能够在 SQL 空间中执行代码,而不是手动返回所有实体。

我也不能使用IQueryable.ToString() 并手动执行它,因为我需要实体框架来填充来自多个.Include 连接的对象。

【问题讨论】:

  • "模型声明函数" (msdn.microsoft.com/en-us/library/ee382839.aspx) 或"模型定义函数" (msdn.microsoft.com/en-us/library/ee382833.aspx) 可能是您的一种方式可以试试。 Code-First 不支持两者,仅支持基于 EDMX 的工作流(DB-First 或 Model-First),而后者需要使用不具备所有 SQL 功能的 Entity SQL。
  • @Slauma 看起来都很有用,但是我坚持使用代码优先,我可能会用它们来争辩说我们应该首先使用 DB,因为无论如何我们都将 DB 与 EF 分开管理
  • 您在哪个 SQL Server 版本上运行您的代码?
  • 我最多可以使用 SQL Server 2012,因此我可以定义一些 CLR 函数来执行我的代码,但我仍然无法使用键入的 Linq .Where(...) 调用它们

标签: sql-server entity-framework linq-to-entities


【解决方案1】:

我不太清楚你的问题。但是,如果您的问题是您不能使用自己的方法或其他 linq to objects 方法,只需使用 .AsEnumerable() 并通过 linq to objects 完成您的其他工作,而不是 L2E:

myQuery.AsEnumerable().Where(entity => entity.Contains('foo', SearchFlags.All))

如果您需要在其他地方多次使用myQuery,请先将其加载到内存中,然后根据需要使用它:

var myQuery = from e in context.myEntities
              select d;
myQuery.Load();

// ...

var myOtherQuery = from d in context.myEntities.Local                        
                    select d;
                    // Now any L2O method is supported...

【讨论】:

  • 在他的问题“明确地说,我不想做...AsEnumerable()...”之后,此建议是否有意义?
  • @Slauma - 我没看到。所以他可以使用第二个......他不能......?!我错了……?!!!
  • AsEnumerable基本相同(将未过滤的数据加载到内存中)。我认为他只是不想将整个表(可能有数百万条记录)加载到内存中并在那里过滤。
【解决方案2】:

我最终做了以下事情(虽然可行,但远非完美):

  1. 我所有的实体都继承自一个IEntity,它定义了long Id { get; set; }
  2. 然后我添加了一个多余的限制 context.myEntities.Where(entity => entity.Id != 0) 这是 冗余,因为标识从 1 开始,但 Linq2Entities 没有 知道这一点。
  3. 完成所有操作后,我在IQueryable 上致电.ToString() 我的其他查询,因为它是DBQuery<Entity> 类型,所以它返回 SQL 命令文本,我用我的查询限制做了一个简单的替换。
  4. 为了让所有.Include(...) 工作,我实际执行 两个不同的 sql 命令。没有其他更漂亮的方法可以利用这一点,因为查询执行计划缓存会导致问题(即使禁用)。

因此,我的代码如下所示:

public IQueryable<IEntity> MyNewFunction(IQueryable<IEntity> myQueryable, string queryRestriction)
{
    string rawSQL = myQueryable.Select(entity => entity.Id).ToString().Replace("[Extent1].Id <> 0", queryRestriction);
    List<long> ids = // now execute rawSQL, get the list of ids;
    return myQuerable.Where(entity => ids.Contains(entity.Id));
}

简而言之,除了手动执行 SQL 或运行类似的 SQL 命令并使用现有命令附加限制之外,将自己的方法写入 Linq-to-Entities 的唯一方法是手动更改和构建自己的 EntityFramework。来自 EF6 源的 dll。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多