c#泛型类型和存储库模式

时间:2015-07-16 22:11:01

标签: c# asp.net-mvc entity-framework generics

我正在使用存储库模式处理C#MVC应用程序。我使用Unity作为我的IoC,以便在MVC应用程序中实现我的存储库。

我创建了以下泛型类型,目的是最大限度地减少整个应用程序中的代码复制。这是一个示例:

public abstract class GenericRepository<T, C> : IDisposable,IGenericRepository<T> where T : class where C : DbContext, new()


public async void AddObjectAsync<T>(T entity) where T : class
    {
        try
        {
            // Validate that that there is not an existing object in the database.
            var x = _context.Entry(entity);
            if (!Exists(entity))
            {
                _context.Set<T>().Add(entity); // Add the entry if it does not exist.
                _context.SaveChanges();
            }
            else
            {
                UpdateObjectAsync(entity); // Update the entry if it did exist.
            }
        }
        catch
        {
            throw;
        }

当我使用TPC或TPH策略时这很有效,但是它不适合TPT策略。一个例子:

public abstract class Component
{
    [Key]
    public Guid ComponentId { get; set; }

    public string Manufacturer { get; set; }
}
public class SpecialComponent : Component
{
    public string ExtraSpecialProperty { get; set; }
}

我在ComponentRepository中的实现:

public class ComponentRepository : GenericRepository<Component, HappyDbContext>, IComponentRepository
{
public async void AddComponentAsync<T>(T component) where T : class
    {
        try
        {

            if(component != null)
            {
                AddObjectAsync(component);
            }
            else
            {
            throw new ArgumentNullException();
            }

        }
        catch (ArgumentNullException ex)
        {
            _logger.WriteErrorLogAsync(ex);
            throw ex;
        }
    }

此代码块的第一行是我遇到的问题。为了初始化GenericRepository类型,我需要为T插入一个类。在这种情况下,DbContext C将始终相同,因此无关紧要。

如何实现可与继承类型一起使用的完全通用模式?如果它是少量的项目,那么我就不那么担心了,但在这种情况下并非如此。我认为有一个更好的方法可以解决这个问题,因此我将全力以赴为您提供意见。

1 个答案:

答案 0 :(得分:0)

看起来你可能有一个“过度泛化”的情况。

如果在{2}中进行硬编码,那么DbContext通用似乎是浪费时间。即GenericRepository<Component, HappyDbContext>where C : DbContext, new()。强类型字段_context并使用强类型仓库中的Unity注入HappyDbContext可能更有意义。

同样将通用实体类型向下移动到方法级别而不是类也可以简化事情:

public interface IGenericRepository
{
    void AddObjectAsync<T>(T entity) where T : class;
}

public class GenericRepository : IGenericRepository
{
    private readonly DbContext _context;

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

    ....

    public async void AddObjectAsync<T>(T entity) where T : class
    {
        // Validate that that there is not an existing object in the database.
        var x = _context.Entry(entity);
        if (!Exists(entity))
        {
            _context.Set<T>().Add(entity); // Add the entry if it does not exist.
            _context.SaveChanges();
        }
        else
        {
            UpdateObjectAsync(entity); // Update the entry if it did exist.
        }
    }
}

public interface IComponentRepository
{
    void AddComponentAsync(Component component);
    // or void AddComponentAsync<T>(T component);
    // depends if you'll be reusing the ComponentRepository 
    // for types that inherit Component but still have individual tables... 
    // It was a little difficult to tell from your example.
}

public class ComponentRepository : GenericRepository, IComponentRepository
{
    public ComponentRepository(DbContext context) : base(context) { }

    ...

    public async void AddComponentAsync(Component component)
    {
        try
        {
            if (component == null) throw new ArgumentNullException();
            AddObjectAsync(component);
        }
        catch (ArgumentNullException ex)
        {
            _logger.WriteErrorLogAsync(ex);
            throw ex;
        }
    }
}

希望这会有所帮助