c# 泛型类型和存储库模式
Posted
技术标签:
【中文标题】c# 泛型类型和存储库模式【英文标题】:c# generic types and repository pattern 【发布时间】:2015-10-06 13:27:09 【问题描述】:我正在使用存储库模式开发 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 将始终相同,因此无需担心。
如何实现适用于继承类型的完全通用模式?如果是少量物品,那么我就不那么担心了,但是在这种情况下并非如此。我认为肯定有更好的方法来处理这个问题,所以我向大家征求意见。
【问题讨论】:
GenericRepository 类的T
参数和AddObjectAsync 的T
参数是什么关系?
在这种情况下您可以使用组合而不是继承吗?如果 ComponentRepository 注入了一个能够构造 GenericRepository 实例的专用工厂,那么AddComponentAsync
可以调用该工厂以根据提供给该方法的类型构造一个强泛型存储库。
对不起,我误读了您的评论。他们是一样的。如果我们传递实体“组件”,则 AddObjectAsync 将是 T
类型相同,则该方法不需要在该级别是通用的。 public async void AddObjectAsync(T entity) ..
可以正常工作。
【参考方案1】:
看起来你可能有“过度通用”的情况。
如果将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;
希望这会有所帮助
【讨论】:
以上是关于c# 泛型类型和存储库模式的主要内容,如果未能解决你的问题,请参考以下文章