Приведение типов в LINQ to Entities
От: Lonely Dog Россия  
Дата: 13.10.10 12:50
Оценка:
Привет!

Есть база данных. В каждой таблице есть поле ID типа GUID. Для этой базы сделан маппинг на объектную модель средствами Entity Framework.
Поверх этого хозяйства навернуты обертки. Изолирующие остальной код от EF (мало ли, захочу перейти на другой ORM или вообще написать его руками в целях самообразования). В итоге имеем следующую картину:

0. Для каждой entity есть соотв. интерфейс:
interface IUser
{
   Guid ID { get;}
   string Username {get; set;}
   string EMail {get; set; } 
}


1. Есть интерфейс IEntitiesCollection<T> следующего вида
interface IEntitiesCollection<T>
{
  T Get(Guid ID);
  void Add(T ent);
  void Remove(T ent);
}


2. для каждой entity есть свой интерфейс коллекции:
interface IUsersCollection : IEntitiesCollection<IUser>
{
 IUser GetByName(string name);
}



3. реализация этого интерфейса на базе EF
class UsersCollection : IUsersCollection
{
  IUser Get(Guid ID)
  {
    // тут LINQ to Entities запрос, результат которого мы оборачиваем в нашу реализацию интерфейса IUser
  }
};



В итоге получается довольно простая в использовании штука. Но!!! Мне приходится реализовывать метод IEntitiesCollection<T>::Get для каждой коллекции. Получается копи-паст. Набросал сл. класс:
interface EntitiesCollectionImpl<T> : IEntitiesCollection<T>
{
  EntitiesCollectionImpl(IQueryable<T> set) {}
  T Get(Guid ID)
  {
    // тот же самый запрос: from obj in set where obj.ID == ID select obj;
  }
}


При компиляции это приводит к ошибке. Т.к. у obj нет свойства ID.
Я выделил это свойство в отдельный интерфейс, т.е. получилось так:
interface IGetID
{
  Guid ID { get;}
};

// благо классы, генерируемые EF имеют атрибут partial, то можно написать вот так:

partial class User : IGetID
{
};


теперь LINQ запрос выглядит так:
from obj in set where ((IGetID)obj).ID == ID select obj;

в итоге, все компилируется, но на этапе выполнения кидается исключение о том, что LINQ To entities поддерживает приведеные только для типов из модели. А про мой интерфейс IGetID он ничего не знает.

Как это побороть?

Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.