【问题标题】:Unit of Work and EF工作单元和 EF
【发布时间】:2010-12-28 12:14:59
【问题描述】:

我正在按照工作单元模式制作界面。我的界面是这样的:

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 作为数据提供者。我为“查询”方法想出了这段代码,但我认为它不是很干净,我觉得有一个聪明的方法可以做到,但我真的想不通。

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));
    }

我在这里看到的问题是所有 IF 每次都经过测试,虽然我可以将它们链接在级联的 if-else 中,但对我来说仍然看起来很糟糕。另一个问题是我必须为每个可能添加的新实体手动添加一行,但这不是我主要关心的问题。

有人对此有什么好的建议吗?谢谢。

【问题讨论】:

  • 什么是_entities?您也许可以将其更改为 _entities.GetEntity&lt;TSource&gt;() 之类的名称,但这取决于它是什么。
  • _entities 是实体框架自动生成的类。

标签: c# design-patterns entity-framework-4 unit-of-work


【解决方案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,但您还需要找到实体 设置名称。

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;
    }
}

【讨论】:

  • 我使用的是 EF4,但我不想每次查询时都重新创建对象集。
【解决方案2】:

一种方法可以不将自动生成的 ObjectContext 与所有预定义的 ObjectSet 一起使用,而是调用:

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

但我不确定每次要执行查询时创建对象集对性能有何影响。我通常会对对象集进行一些延迟初始化(使用字典来存储已创建的对象集)并将它们重用于单个工作单元实例。

【讨论】:

  • 这正是它的工作原理,这是我试图保留的一些行为。也许毕竟没有更清洁的模式可以做到这一点。至少每次都调用 CreateObjectSet。
猜你喜欢
  • 2013-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-11
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
  • 2011-11-16
相关资源
最近更新 更多