2010-12-28 4 views
1

Я создаю интерфейс, следуя шаблону «Единица работы». Мой интерфейс выглядит так:Единица работы и EF

public interface IDataContext : IDisposable 
{ 
    void SaveChanges(); 
    TSource Create<TSource>(TSource toCreate) where TSource : class; 
    TSource Update<TSource>(TSource toUpdate) where TSource : class; 
    bool Delete<TSource>(TSource toDelete) where TSource : class; 
    IQueryable<TSource> Query<TSource>(); 
} 

Пока все хорошо. Теперь я реализую его в своем слое данных, который использует EF4 в качестве поставщика данных. Я придумал этот код для метода «Query», но я думаю, что это не очень чисто, я считаю, что есть умный способ сделать это, но я не могу понять.

public IQueryable<TSource> Query<TSource>() 
    { 
     var type = typeof(TSource); 
     IQueryable item = null; 

     if (type == typeof(Activity)) item = _entities.ActivitySet; 
     if (type == typeof(Company)) item = _entities.CompanySet; 
     if (type == typeof(Phase)) item = _entities.PhasesSet; 
     if (type == typeof(Project)) item = _entities.ProjectSet; 
     if (type == typeof(ProjectState)) item = _entities.ProjectStateSet; 
     if (type == typeof(ProjectType)) item = _entities.ProjectTypeSet; 
     if (type == typeof(User)) item = _entities.UserSet; 
     if (type == typeof(UserType)) item = _entities.UserTypeSet; 
     if (item != null) return item as IQueryable<TSource>; 

     throw new NotImplementedException(string.Format("Query not implemented for type {0}", type.FullName)); 
    } 

Проблемы я вижу здесь все МСФ пройти тестирование каждый раз, Althought я мог цепную их в каскадном если-то еще, но по-прежнему выглядит довольно ужасно для меня. Другие проблемы состоят в том, что я должен вручную добавить одну строку для каждой новой сущности, которая может быть добавлена, но это не моя основная проблема.

У кого-нибудь есть хороший совет по этому вопросу? Благодарю.

+0

Что такое '_entities'? Возможно, вы сможете изменить его на что-то вроде '_entities.GetEntity ()', но это зависит от того, что это такое. – SwDevMan81

+0

_entities - это автогенерируемый класс Entity Framework. –

ответ

1

Если вы используете EF4, вы можете просто вызвать CreateObjectSet <>.

using System; 
using System.Collections.Generic; 
using System.Data.Objects; 
using System.Linq; 

namespace WindowsFormsApplication1 
{ 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      var context = new DataContext(new NorthwindEntities()); 
      var list = context.Query<Customer>().ToList(); 
      var list2 = context.Query<Customer>().ToList(); 
     } 
    } 

    public class DataContext : IDataContext 
    { 
     private Dictionary<Type, object> _objectSets = new Dictionary<Type,object>(); 
     private ObjectContext _entities; 

     public DataContext(ObjectContext objectContext) 
     { 
      this._entities = objectContext; 
     } 

     public IQueryable<T> Query<T>() 
      where T : class 
     { 
      Type entityType = typeof(T); 
      ObjectSet<T> objectSet; 

      if (this._objectSets.ContainsKey(entityType)) 
      { 
       objectSet = this._objectSets[entityType] as ObjectSet<T>; 
      } 
      else 
      { 
       objectSet = this._entities.CreateObjectSet<T>(); 
       this._objectSets.Add(entityType, objectSet); 
      } 

      return objectSet; 
     } 
    } 

    interface IDataContext 
    { 
     IQueryable<T> Query<T>() where T : class; 
    } 
} 

Если вы используете EF1 вы можете позвонить CreateQuery <> но вы также должны найти Entity Set Name.

using System; 
using System.Collections.Generic; 
using System.Data.Metadata.Edm; 
using System.Data.Objects; 
using System.Linq; 

namespace WindowsFormsApplication2 
{ 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      var context = new DataContext(new NorthwindEntities()); 
      var list = context.Query<Customer>().ToList(); 
     } 
    } 

    public class DataContext : IDataContext 
    { 
     private Dictionary<string, string> _entitySets; 
     private ObjectContext _entities; 

     public DataContext(ObjectContext objectContext) 
     { 
      this._entities = objectContext; 
     } 

     public IQueryable<T> Query<T>() 
      where T : class 
     { 
      return this._entities.CreateQuery<T>(this.GetEntitySetName<T>()); 
     } 

     private string GetEntitySetName<T>() 
      where T : class 
     { 
      if (this._entitySets == null) 
      { 
       // create a dictionary of the Entity Type/EntitySet Name 
       this._entitySets = this._entities.MetadataWorkspace 
               .GetItems<EntityContainer>(DataSpace.CSpace) 
               .First() 
               .BaseEntitySets.OfType<EntitySet>().ToList() 
               .ToDictionary(d => d.ElementType.Name, d => d.Name); 
      } 

      Type entityType = typeof(T); 

      // lookup the entity set name based on the entityType 
      return this._entitySets[entityType.Name]; 
     } 
    } 

    interface IDataContext 
    { 
     IQueryable<T> Query<T>() where T : class; 
    } 
} 
+0

Я использую EF4, но я не хочу воссоздавать набор объектов каждый раз, когда я его запрашиваю. –

+0

Я редактировал пример EF4, чтобы включить кеширование объекта ObjectSet. –

0

Одним из способов может быть не используется автоматически сформированное ObjectContext со всеми предопределенными ObjectSets и вместо того, чтобы позвонить:

public IQueryable<TSource> Query<TSource> 
{ 
    return _entities.CreateObjectSet<TSource>(); 
} 

Но я не уверен, что влияет на производительность имеет создание объекта устанавливается каждый раз, когда вы хотите, чтобы выполнить запрос. Обычно у меня есть ленивая инициализация наборов объектов (с использованием словаря для хранения уже созданных наборов объектов) и повторного использования их для одного экземпляра рабочей единицы.

+0

Вот как это работает, и это какое-то поведение, которое я пытаюсь сохранить. Возможно, в конце концов нет более чистого режима. Не обойтись без вызова CreateObjectSet каждый раз, по крайней мере. –

Смежные вопросы