Отображение выражений в абстрактном классе LINQ-to-sql

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

Ниже приведен очень простой код, который показывает, что я имею в виду. Автомобиль и мотоцикл имеют полностью отдельные реализации _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 expression, либо свойство IsNew на IQueryable, и все же он запускает класс _isNew класса Car в случае, если Vehicle является типом автомобиля. В любом случае, я могу это сделать? Все решения, которые я пробовал, вызвали исключение, которое невозможно передать в SQL.

Ответ 1

Прежде чем я войду в ваш вопрос, вы должны, вероятно, проверить лучшие практики свойств С#, касающихся исключений.

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

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

Итак, если вы не можете использовать экземпляр, , что следующая лучшая вещь?

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

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 как вычисленный столбец, который я лично считаю вашим лучшим вариантом.

Ответ 2

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

var vehicule = new Car();