Как искать сущности в EntityFramework 4 с помощью интерфейса поиска?(работает в LinqToSql) - PullRequest
2 голосов
/ 04 ноября 2010

У меня есть уровень репозитория, к которому мои приложения обращаются, который можно инициализировать с помощью IDataSource; например LinqToSqlDataSource, EntityFrameworkDataSource и т. Д. ...

IDataSource предоставляет методы для вставки, обновления, удаления и запроса источника данных соответственно. Относительно этого вопроса является то, что FindAll<T> возвращает IQueryable<T>.

Все мои базовые сущности реализуют простой интерфейс, чтобы сделать поиск сущностей по идентификатору универсальным и удобным;

public interface IAmIdentifiable<T>
{
    T Id { get; set; }
}

Ниже приведен соответствующий код для метода FindById<T, TKey>, с которым у меня возникают проблемы в EntityFramework.

public class Repository
{
    public Repository(IDataSource dataSource)
    {...}

    public T FindById<T, TKey>(TKey identifier) where T : class, IAmIdentifiable<TKey>
    {
        return _DataSource.FindAll<T>().SingleOrDefault(i => i.Id.Equals(identifier));
    }

    ...
}

Этот FindById<T, Tkey>(...) отлично работает с LinqToSql, но не работает в EntityFramework 4 .

Пример использования

User user = Repository.FindById<User, int>(someUserId);
Message msg = Repository.FindById<Message, Guid>(someMessageId);

Когда приведенный выше код запускается с реализацией IDataSource EntityFramework 4, он выдает следующую ошибку:

Невозможно создать постоянное значение типа 'System.Object'. В этом контексте поддерживаются только примитивные типы (такие как Int32, String и Guid).

Я попытался изменить это, чтобы выполнить сравнение == для типов значений. Я прочитал, что окольный способ ограничения универсального значения на тип значения состоит в ограничении struct. Я обновил базовый интерфейс для всех сущностей и средства поиска репозитория соответственно ...

public interface IAmIdentifiable<T> where T : struct
{
    T Id { get; set; }
}

public T FindById<T, TKey>(TKey identifier)
    where T : class, IAmIdentifiable<TKey>
    where TKey : struct
{
    return _DataSource.FindAll<T>().SingleOrDefault(i => i.Id == identifier);
}

Однако это все равно приводит к ошибке компиляции;

Ошибка 59 Оператор '==' не может быть применен к операндам типа 'TKey' и 'TKey'

Кто-нибудь может пролить некоторый свет на то, как я мог бы привести приведение этих сущностей к интерфейсу IAmIdentifiable<T>, чтобы иметь общий способ получения сущностей по Id?

Ответы [ 2 ]

0 голосов
/ 10 ноября 2012

Не спрашивайте меня, почему это работает, но нам удалось сделать это, выполнив:

i => (object)i.Id == (object)identifier

Каким-то образом это ведет себя хорошо и пишет правильное предложение SQL WHERE.Все остальные альтернативы, которые мы попробовали, не сработали.

0 голосов
/ 04 ноября 2010

Я думаю, что ошибка заключается в том, что вы пытаетесь сравнить универсальный TKey. Поскольку TKey является сложным типом, оператор == должен быть явно реализован, чтобы сделать это сравнение. Теперь с универсальным TKey нет никаких гарантий, что это так. Возможно, есть еще одно общее ограничение, которое вы можете наложить на TKey, чтобы обеспечить доступность метода сравнения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...