尝试使用Linq to SQL来处理我正在家里工作的小项目。我已经使用dbmetal.exe(来自DBLinq项目)针对本地MySQL数据库生成了上下文代码和所有实体类。
一切都运行良好,但我正在尝试抽象一些冗余代码,我遇到了试图这样做的问题。
基本上我的所有实体在我的上下文类中都是Table<TEntity>
类型。例如,我有Table<User>
和Table<Calendar>
。
当我构建存储库行为的各种接口时,我意识到有些方法对每个实体都非常冗余。例如ID字段:
User findById(int id);
Calendar findById(int id);
我设计了表格,因此它们共有3个共同字段[ID,DATECREATED,DATEUPDATED]。由于这些字段很常见,我希望有一个共同的行为,而不是为每个实体重写这些方法。
所以我使我的存储库类(UserRepository,CalendarRepository)继承了一个通用的“Repository”类,其定义如下:
public class Repository<T> : IDisposable, IRepository<T> where T : class
{
protected MyContext context;
private DbLinq.Data.Linq.Table<T> currentTable;
protected Repository() {
context = new MyContext();
Type currentType = this.GetType().GetGenericArguments()[0];
currentTable = //Set currentTable based on currentType. e.g.: currentTable = context.User;
}
#region IRepository<T> Members
public T findById(int? id)
{
return currentTable.SingleOrDefault(d => d.ID == id);
}
public T findByDateCreated(DateTime dateCreated)
{
return currentTable.SingleOrDefault(d => DateTime.Equals(dateCreated, d.DateCreated));
}
public T findByDateUpdated(DateTime dateUpdated)
{
return currentTable.SingleOrDefault(d => DateTime.Equals(dateUpdated, d.DateUpdated));
}
public T insert(T domainObject)
{
currentTable.InsertOnSubmit(domainObject);
return domainObject;
}
public T save(T domainObject)
{
context.SubmitChanges();
return domainObject;
}
#endregion
#region IDisposable Members
public void Dispose()
{
if (context != null)
context.Dispose();
}
#endregion
}
事实证明这比我想象的要困难。当我尝试设置:
currentTable = (Table<T>)context.User;
我收到以下错误:
Cannot convert type 'DbLinq.Data.Linq.Table<Models.Domain.User>' to 'DbLinq.Data.Linq.Table<T>'
隐式投射也不起作用。
有没有人成功做过类似的事情?如果我必须让我的所有Repository类都使用完全相同的代码实现相同的findById方法,那将是非常难过的......我确信有一种方法可以不这样做,我只是找不到它。 :)
答案 0 :(得分:4)
如果必须的话,那会非常难过 我的所有Repository类都实现了 完全相同的findById方法 其中的代码相同
代码并不完全相同。在每种情况下,您指的是上下文中的不同表格。
我理解你的逻辑;你想要干。但是您拥有存储库的原因是为了使您能够通过注入模拟存储库而不是真实存储库来抽象数据访问逻辑,以便于单元测试。最实用(也是最灵活)的方法是使表(和DAL对象)保持独立和不同。通过尝试对部分DAL对象进行泛化,您将引入额外的耦合,这将使单元测试变得复杂。