Проблема Linq To SQL - не поддерживается перевод на SQL (проблема со свойством C #) - PullRequest
14 голосов
/ 18 января 2010

Я расширяю некоторые классы Linq для SQL. У меня есть 2 аналогичных утверждения, первое работает, второе не (ошибка «не поддерживается перевод в SQL»).

var reg2 = rs.ProductRegistrations().SingleOrDefault(p => p.Product.product_name == "ACE")

var reg5 = rs.ProductRegistrations().SingleOrDefault(p => p.product_name == "ACE");

После прочтения этой ссылки LINQ: Нет перевода на SQL

Я понимаю (я думаю), что в основном все должно быть "встроенным", иначе дерево выражений не может быть правильно рассчитано. Первый пример напрямую обращается к LinqToSql EntitySet «Product» (сохраняя все в строке), тогда как во втором примере используется свойство, которое определяется следующим образом:

public partial class ProductRegistration :IProduct
{
    public string product_name
    {
        get { return this.Product.product_name; }
    }
}

Я предполагаю, что моя проблема в том, что LinqToSql не может перевести это.

Как бы я превратил "свойство" в эквивалентное утверждение? Я знаю, что должен использовать System.Linq.Expressions.Expression, но все, что я пробовал, не работает (некоторые даже не компилируются). Может быть, мне следует создать метод Extension (используя Expression), а затем вызвать его из свойства? Может ли свойство вызвать метод расширения ??

Такие вещи, как показано ниже, не работают:

public static System.Linq.Expressions.Expression<Func<IProduct, bool>> ProductName2 (string pname)
{
    return (p => p.product_name == pname);
}

Итог, я знаю, что мне нужно обернуть мой метод доступа в "выражение <....>", но я не знаю, как получить к нему доступ из свойства, чтобы приведенная выше переменная "reg5" работала правильно.

Было бы замечательно, если бы был какой-то магический атрибут, который я мог бы просто добавить к свойству, чтобы "автоматически выражать" свойство и сделать LinqToSql счастливым, вместо того, чтобы заключать его в выражение <...>

Хотел бы иметь возможность сделать это ...

public partial class ProductRegistration :IProduct
{
    [Auto-Expression]
    public string product_name
    {
        get { return this.Product.product_name; }
    }
}

EDIT Ссылка и ответ ниже работает. Круто, спасибо. 2-я часть моего вопроса, снова у меня есть 2 аналогичных утверждения, 1-е работает, 2-е не (ошибка «не поддерживается перевод в SQL»).

var reg = rs.ProductRegistrations().ProductName("ACE").WithTranslations().SingleOrDefault();

var reg2 = rs.ProductRegistrations2().ProductName("ACE").WithTranslations().SingleOrDefault();

Различие в том, что 1-й возвращает IQueryable конкретного класса"IQueryable [ProductRegistration]", тогда как 2-й возвращает IQueryable интерфейса"IQueryable [IProduct]». Я хотел бы использовать 2-й, потому что я могу дать интерфейс многим различным классам, и это более общий способ, но, похоже, он не работает. Есть идеи?

1 Ответ

10 голосов
/ 18 января 2010

Было бы замечательно, если бы был какой-то магический атрибут, который я мог бы просто добавить к свойству, чтобы "автоматически выражать" свойство и сделать LinqToSql счастливым, вместо того, чтобы заключать его в выражение <...>

Есть, очень близко.Вам все равно придется проделать некоторую работу, но Damien Guard и его друзья выполнили для вас сложную часть: Свойства на стороне клиента и любого удаленного поставщика LINQ

Круто то, что он работает с любым провайдером LINQ, который поддерживает используемые вами выражения.

Обновление: Проблема с вашей второй версией (с интерфейсом) заключается в том, что провайдеру Queryable потребуетсячтобы иметь возможность выяснить, что является разработчиком интерфейса, потому что он должен транслитерировать это в имя таблицы.Но весь смысл интерфейса заключается в том, что пользователь интерфейса должен быть независимым от типа реализации, поэтому поставщик будет работать в разных целях с интерфейсом.Поэтому я не думаю, что вторая форма будет работать.

...