1

Unit of Work パターンに従ってインターフェイスを作成しています。私のインターフェースは次のようになります。

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 でそれらをチェーンすることはできますが、それでもかなりひどいように見えます。その他の問題は、追加される可能性のある新しいエンティティごとに 1 行を手動で追加する必要があることですが、それは私の主な関心事ではありません。

誰でもこれについて何か良いアドバイスはありますか? ありがとう。

4

2 に答える 2

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;
    }
}
于 2010-12-28T13:47:20.067 に答える
0

1 つの方法は、自動生成された ObjectContext を事前定義済みのすべての ObjectSet で使用せず、代わりに以下を呼び出すことです。

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

しかし、クエリを実行するたびにオブジェクトセットを作成することで、パフォーマンスにどのような影響があるかはわかりません。私は通常、オブジェクト セットの遅延初期化 (辞書を使用して既に作成されたオブジェクト セットを格納する) を行い、それらを単一の作業単位インスタンスに再利用します。

于 2010-12-28T13:45:50.753 に答える