如何使用EF5和Database First生成的上下文类与Repository和UoW

时间:2013-01-17 19:18:27

标签: entity-framework repository-pattern

我使用数据库优先方法在VS.NET 2012中使用Entity Framework 5。我还尝试实现标准的通用存储库接口以及工作单元,以确保所有更新都在单个上下文中发生。创建存储库,UoW,使用DI注入它实际上 我知道如何完成的部分。

我遇到的问题是了解它与下面的MyModel.Context.cs类如何相关,该类是从Entity Framework 5 T4 POCO模板自动生成的:

public partial class AdventureWorks2008R2Entities : DbContext
{
    public AdventureWorks2008R2Entities() : base("name=AdventureWorks2008R2Entities")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public DbSet<Person> People { get; set; }
    public DbSet<PersonPhone> PersonPhones { get; set; }
    public DbSet<PhoneNumberType> PhoneNumberTypes { get; set; }
}

我认为将要发生的事情是,这个类的一个实例将被发送到我的UoW类的构造函数,如下所示:

public UnitOfWork(IContext context)
{
    _context = context;
}

所以我的主要问题是,自动生成的上下文类和我创建的存储库(使用UoW)应该如何协同工作。我在EF4中首先使用代码找到了一些示例,但对于使用POCO生成和存储库模式的Database First方法,EF5没有任何示例。如果有人知道这方面的好例子,请分享。

感谢您提供帮助以解决此问题,谢谢!

2 个答案:

答案 0 :(得分:1)

好的,我想出了一个解决这个问题的方法。要开始此方法实际上可以用于Database 1st或Code 1st方法,因为Context不会被修改,只使用它的一个实例。

某些示例将IUnitOfWork接口直接应用于自动生成的AdventureWorks2008R2Entities类。但是你不想这样做,因为修改可能被覆盖的自动生成的代码并不是一个好主意。

我们的想法是让通用存储库(或者如果不使用通用存储库,每个存储库)接收EF Context的实例,如下所示:

public GenericRepository(DbContext context)
{
    this.context = context;
    this.dbSet = context.Set<TEntity>();
}

现在,IUnitOfWork接口应声明EF的方法和每个存储库类型的实例,如下所示:

public interface IUnitOfWork : IDisposable
{
    GenericRepository<Person> PersonRepository { get; }
    GenericRepository<PersonPhone> PersonPhoneRepository { get; }
    void Save();
}

如果尚未实例化,则实现将新建一个存储库实例:

public class UnitOfWork:IUnitOfWork {     private DbContext _context;     private GenericRepository _personRepository;     private GenericRepository _personPhoneRepository;

public UnitOfWork(DbContext context)
{
    _context = context;
}

public GenericRepository<Person> PersonRepository
{
    get
    {

        if (this._personRepository == null)
        {
            this._personRepository = new GenericRepository<Person>(_context);
        }
        return _personRepository;
    }
}

public GenericRepository<PersonPhone> PersonPhoneRepository
{
    get
    {

        if (this._personPhoneRepository == null)
        {
            this._personPhoneRepository = new GenericRepository<PersonPhone>(_context);
        }
        return _personPhoneRepository;
    }
}

public void Save()
{
    try
    {
        _context.SaveChanges();
    }
    catch (DbEntityValidationException dbEx)
    {
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
            foreach (var validationError in validationErrors.ValidationErrors)
            {
                Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
            }
        }
    }

}

#region Implementation of IDisposable

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

/// <summary>
/// Disposes off the managed and unmanaged resources used.
/// </summary>
/// <param name="disposing"></param>
private void Dispose(bool disposing)
{
    if (!disposing)
        return;

    if (_disposed)
        return;

    _disposed = true;
}

private bool _disposed;
#endregion

}

最后,要使用您的存储库的工作单元实例,您可以通过它到达相应的存储库实例,并且UoW将负责确保所有更改都发生在上相同的上下文:

_unitOfWork.PersonRepository.Insert(person);
_unitOfWork.Save();

答案 1 :(得分:0)