2016-06-03 11 views
11

У меня есть абстрактный класс, который унаследован двумя классами. Оба класса представляют таблицы в базе данных. У меня возникли проблемы с отображением выражений, хотя в абстрактном классе, и поэтому я получаю исключения, которые не могут быть переведены на SQL. Все вопросы, которые я нашел в Stackoverflow, говорят о столбцах, которые уже работают для меня.Отображение выражений в абстрактном классе LINQ-to-sq

Ниже приведен очень простой код, который показывает, что я имею в виду. У автомобилей и мотоциклов есть полностью отдельные реализации _isNew Expression.

public abstract class Vehicle { 
    public abstract boolean IsNew; 
} 

public partial class Car: Vehicle { 
     public override boolean IsNew { 
     get { _isNew.Invoke(this); } 
     } 
} 
public partial class Motorcycle: Vehicle { 
     public override boolean IsNew { 
     get { _isNew.Invoke(this); } 
     } 
} 

Я хотел бы иметь возможность вызывать либо _isNew выражения или свойство IsNew на IQueryable, и все же она бежит _isNew класса автомобиля в случае транспортного средства является типом автомобиля. В любом случае, я могу это сделать? Все решения, которые я пробовал, вызвали исключение, которое невозможно перевести на SQL.

+0

Что такое '_isNew'? Не может быть выражением, которое * может * быть переведено? –

+0

_isNew - это выражение, которое может быть переведено в SQL (например, для автомобилей Выражение > _isNew = (v) => v.Age <2; для мотоциклов Выражение > _isNew = (v) => v.Age <1; (PS: возраст - это столбец DB). Моя основная проблема заключается в том, как я могу выбрать правильный _isNew для вызова на Транспортном средстве в зависимости от унаследованного класса. функция IsNew вызовет ошибку SQL-перевода, и я не могу решить, для чего _IsNew вызывать, не проверяя тип и кастинг каждый раз. – Sami

+0

Я предполагаю, что это не сработает, потому что для вызова вашего переопределения IsNew вам понадобится конкретный пример либо автомобиля, либо мотоцикла. В результате EF придется сначала запросить элементы для создания этих экземпляров. – Peit

ответ

1

Прежде чем я войду в ваш вопрос, вы должны, вероятно, проверить на best practices of C# properties concerning exceptions.

Вы можете просто загрузить свой список, а затем вызвать свойство IsNew после этого, что устранит ошибку Linq-to-SQL. Но я понимаю, что это может вызвать проблемы с производительностью, если вы полагаетесь на IsNew для фильтрации большого набора данных внутри.

Я думаю, что ваша проблема действительно связана с тем, что вы хотите использовать экземпляр , чтобы получить свойство «IsNew». Но вы просто не можете сделать это, потому что linq-to-sql будет справедливо жаловаться when you are trying to use a property that is not mapped to a column.

Так что, если вы не можете использовать экземпляр, что нового?

Ну, может быть, я бы оседать на статическом выражении

public partial class Motorcycle : Vehicle 
{ 
    public static Expression<Func<Vehicle, bool>> IsNew { get { return (v) => v.Age <= 1; } } 
} 

public partial class Car : Vehicle 
{ 
    public static Expression<Func<Vehicle, bool>> IsNew { get { return (v) => v.Age <= 2; } } 
} 

, который можно использовать как

var newCars = db.Cars.Where(Car.IsNew).ToList(); 
var newMotorcycles = db.Motorcycles.Where(Motorcycle.IsNew).ToList(); 

Или вы могли бы потянуть логику вне приложение и сделать это в SQL Server как computed column, который я лично считаю вашим лучшим вариантом.

+0

Благодарим вас за ответ. Моя основная проблема с вашим предложением заключается в том, что я не всегда знаю тип, поэтому в конечном итоге я добавлю типof во многих местах и ​​кастинг, прежде чем я запустим выражение IsNew. Я пришел к выводу, что просто не могу сделать это с помощью LINQ, но сумел найти какое-то грязное обходное решение: я использовал LINQKit ExpandableQuery и расширил всю логику, чтобы выбрать правильное выражение. Таким образом, класс Vehicle никогда не отправляется в LINQ, и там обрабатываются только автомобили и мотоциклы. Не очень чистое решение, хотя – Sami

+0

Я решительно согласен с вами в отношении вычисленных столбцов, хранимых процедур, представлений для обработки всего в SQL Server. Но я работаю над существующим крупным проектом со всеми выражениями, уже определенными в LINQ. Потребуются месяцы, чтобы переписать их, и поэтому предпочли найти метод LINQ. – Sami

+0

Я не могу помочь, но чувствую, что каким-то образом отражение могло каким-то образом помочь вам, это довольно запутанный аспект C#, если у вас еще нет опыта с ним, возможно, неэффективно использовать время. Хотя я лично обнаружил, что жесткие структурные проблемы, подобные этому, часто можно решить с отражением. – Shadetheartist

0

Абстрактный класс позволяет принудительно унаследовать класс для реализации свойства IsNew. Это просто базовый класс. Вы должны использовать реализацию Car или Motorcycle, и для этого вам следует бросить свой автомобильный объект как автомобиль или мотоцикл, чтобы было вызвано правильное свойство IsNew.

var vehicule = new Car(); 
+0

Речь идет о переводе linq-to-sql двух классов с отображением в базу данных и родительским абстрактным классом. Это не просто нормальный класс наследования/абстрактности. – Sami