2009-11-07 42 views
3

试图将Linq to SQL用于我在家工作的小项目。我已经使用dbmetal.exe(来自DBLinq项目)针对本地MySQL数据库生成了上下文代码和所有实体类。通用表<TEntity>

一切都很好,但我想抽象一些冗余代码,我遇到了试图这样做的问题。

基本上我所有的实体在我的上下文类中都是Table<TEntity>类型。例如,我有Table<User>和​​。

当我构建存储库行为的各种接口时,我意识到存在一些对每个实体都非常冗余的方法。例如,ID字段:

User findById(int id); 
Calendar findById(int id); 

我设计我的表,以便它们都具有共同的[ID,dateCreated会,DATEUPDATED] 3个字段。由于这些字段很常见,我想要有一个共同的行为,而不是为每个实体重写这些方法。

所以我做了我的仓库类(UserRepository,CalendarRepository)会沿用这样定义一个共同的“信息库”类:

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

它在编译时或运行时失败吗? – eglasius 2009-11-08 00:06:23

回答

4

That'd be very sad if I had to have all my Repository classes implement the same findById method with exactly the same code in it

代码不完全一样。在每种情况下,您都指的是您的上下文中的不同表格。

我明白你的逻辑;你想成为干的。但是你有一个仓库的原因是为了让你能够通过注入一个模拟仓库而不是真正的仓库来简化单元测试,从而将数据访问逻辑抽象出来。做到这一点最实际(也是最灵活)的方法是让你的表格(和你的DAL对象)分开和独立。通过尝试泛化部分DAL对象,您将引入额外的耦合,这会使您的单元测试复杂化。

+0

确实引用的对象是不同的,但代码是相同的。但我确实得到了单元测试的观点...... IOC实际上是我使用Ninject的下一步之一。感谢您的帮助罗伯特。 – Lancelot 2009-11-08 00:11:04

+0

@Robert是单元测试仍然很重要,即使我有5个完全相同的方法表?如果我想牺牲单元测试以获得更多的干燥度,我该怎么做?我在3天前和Lancelot一样苦恼,仍然无法创建一个通用结构来接受我所有的Log表。 – AdrianoRR 2012-01-06 14:19:59

+0

@AdrianoRR:为了澄清,存储库的目的是抽象出您的数据持久性。这可以用来简化单元测试,或者可以用不同的供应商替换底层的数据存储。在实践中,单元测试只是用来确认存储库方法返回正确的记录,并且几乎不会发生数据存储的交换。 – 2012-01-06 17:04:34