将Where()转换为sql

时间:2010-02-24 17:56:40

标签: c# linq-to-sql .net-3.5 custom-linq-providers

我看到DamienG的文章(http://damieng.com/blog/2009/06/24/client-side-properties-and-any-remote-linq-provider)介绍了如何将客户端属性映射到sql。 我跑了这篇文章,我看到了它的巨大潜力。绝对将客户端属性映射到SQL是一个很棒的想法。

但是我想把它用于比复杂字符串更复杂的东西。我们正在尝试向我们的Business对象引入多语言,我希望我们可以保留所有现有的linq2sql查询,只需更改多语言属性的代码,这样他们就会实际返回CurrentUICulture中的给定属性。

第一个想法是将这些字段更改为XML,然后尝试Object.Property.Elements()。Where(...),但它被卡在Elements()上,因为它无法将其转换为sql 。我在某处读到XML字段实际上被视为字符串,并且只在应用服务器上它们变成了XElements,因此这样过滤将在应用服务器上进行,而不是数据库。公平点,它不会像这样工作。让我们试试别的...... 所以第二个想法是创建一个PolyGlots表(名称取自http://weblogic.sys-con.com/node/102698?page=0,1),一个PolyGlotTranslations表和一个Culture表,其中PolyGlots将从每个国际化的属性中引用。这样我就想说:

private static readonly CompiledExpression<Announcement, string> nameExpression
    = DefaultTranslationOf<Announcement>
        .Property(e => e.Name)
        .Is(e=> e.NamePolyGlot.PolyGlotTranslations
          .Where(t=> t.Culture.Code == Thread.CurrentThread.CurrentUICulture.Name)
          .Single().Value
        );

现在不幸在这里我得到一个错误,Where()函数无法转换为sql,有点令人失望,因为我确信它会通过。 我猜它是失败的,因为IEntitySet基本上是一个IEnumerable,而不是IQueryable,我是对的吗?

还有另一种方法可以使用compiledExpressions类来实现这个目标吗? 任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

首先,我不会尝试将XML扩展转换为SQL。它们是为不同的野兽而设计的。

使用正确的数据库策略,您应该能够使用一组linq查询。 (您可能需要调整它们以适应新模型。)例如,如果根据语言有不同的描述字段,则创建一个视图,该视图将根据所选语言返回正确的描述。现在将您的linq查询指向视图而不是表。

其他信息: 每个项目只有一个视图,其中包含多语言字段。每个多语言字段都有自己的表,使用语言表键,原始对象的键作为复合键。视图将所有表组合回一个地方进行查询。现在说我们有产品视图。如果我通过ProductId = 1查询该视图,我实际上会看到与语言一样多的产品副本。

现在,您的Linq查询将始终包含一个按语言限制的参数。只需确保在查询中使用外部联接,这样如果缺少某种语言的描述,您仍会将其恢复。 (或者不使用它来故意将项目限制为所选语言的设置。

您可以创建存储过程以打开更新视图的功能,使其像表一样运行。 (或者你可以通过在那里连接存储过程来对大多数ARM框架执行此操作。)

答案 1 :(得分:0)

嗯,实际问题是,Where使用的不是System.Linq命名空间中的那个,而是另一个,并且ef的表达式访问者无法翻译。