5

EF 4 を使用して新しいプロジェクトを開始することを考えており、いくつかの記事を読んでいると、リポジトリ パターンと作業単位を含む EF に関する記事を見つけました ( http://blogs.msdn.com/b/adonet/archive/2009/ 06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx )

その記事を見ると、ObjectContext を UnitOfWork として使用し、それをリポジトリに渡しています。

私の質問は、2 つの ObjectContext がある場合、つまり 2 つの作業単位がある場合ですが、実際には、これら 2 つのコンテキストで実行されるすべての操作を 1 つの作業単位にしたいのですが、このシナリオは可能ですか? 各コンテキストで save を呼び出したくありません.transactionalにしたいのですが.... transactionscopeを使わずに...

たとえば、操作ログを管理するコンテキストと、注文を管理する別のコンテキストがあります。私のビジネス層には、AddOrder() というメソッドがあるとしましょう。AddOrder() は注文コンテキストを使用して新しい注文を作成しますが、操作ログ コンテキストも使用して新しい操作ログ エントリを作成します。これらは 2 つのコンテキストであるため、両方のコンテキストで save を呼び出してコミットする必要があります....おそらく唯一のオプションは、単一のコンテキストのみを使用することです....

編集: たとえば、OperationalLogContext と OrderContext など、異なるタイプの 2 つのコンテキストを意味しました。

4

1 に答える 1

12

うん - 私はそれが可能だと信じています。

キッカーは、リポジトリの処理方法です。

たとえば、各リポジトリはコンテキストを取得する必要があるため、コンテキストを 1 つ作成して各リポジトリに渡します。

(コードをお願いします!) よろしくお願いします :)

public interface IOrderRepository
{
    IQueryable<Order> FindAll();
}

public interface IOperationLogRepository
{
    IQueryable<OperationLog> FindAll();
}

public interface IUnitOfWork
{
    void Commit();
}

.

public class SqlServerContext : ObjectContext, IUnitOfWork
{
    public void SqlServerContext(string connectionString) 
        : base(connectionString)
    {
    }

    public void Commit()
    {
        this.SaveChanges();
    }

    // Your other POCO's and stuff here ..etc..
}

.

public class OrderRepostiory : IOrderRepository
{
    private readonly SqlServerContext _sqlServerContext;
    public void OrderRepostiory(SqlServerContext sqlServerContext)
    {
        _sqlServerContext = sqlServerContext;
    }

    public IQueryable<Order> FindAll()
    {
        _sqlServerContext.Orders;
    }
}

..そして最後に、インスタンス化。あなたの良い男の子/女の子/虹のユニコーンの原因は、依存性注入を使用しているでしょう..

public class SqlServerRegistry : Registry
{
    public SqlServerRegistry(string connectionString)
    {
        For<SqlServerContext>()
            .HybridHttpOrThreadLocalScoped()
            .Use<SqlServerContext>()
            .Ctor<string>("connectionString")
                .Is(connectionString);

        For<IOrderRepository>().Use<OrderRepository>();
        For<IOperationLogRepository>().Use<OperationLogRepository>();
    }
}

SqlServerContext は HttpOrThreadLocal として定義されているため、一度インスタンス化され、複数のリポジトリで再利用されます。

DI/IoC を知らない、または理解していませんか?

その後、これも機能します....

private SqlServerContext _sqlServerContext;
private IOrderRepository _orderRepository;
private IOperationLogRepository _operationLogRepository;

[TestInitialize]
public void TestInitialise()
{
    _sqlServerContext = new SqlServerContext(
             ConfigurationManager.AppSettings["connectionString"]);
    _orderRepository = new OrderRepository(_sqlServerContext);
    _operationLogRepository= new OperationLogRepository(_sqlServerContext);
}

[TestMethod]
public void SomeTest()
{
    // Arrange.
    const int count = 10;

    // Act.
    var orders = _orderRepository.FindAll().Take(10).ToArray();

    // Assert.
    Assert.IsNotNull(orders);
    CollectionAssert.AllItemsAreNotNull(orders);
    Assert.AreEqual(count, orders.Length);
}

繰り返しになりますが、この質問に答えようと考えていたときに入力したすべての未テストのコードです。

HTH。

于 2010-09-15T03:07:22.347 に答える