c# - 通用表<TEntity>

标签 c# generics linq-to-sql entity

尝试使用 Linq to SQL 来完成我在家进行的一个小项目。我已经使用 dbmetal.exe(来自 DBLinq 项目)针对本地 MySQL 数据库生成了上下文代码和所有实体类。

一切都运行良好,但我正在尝试抽象一些冗余代码,并且在尝试这样做时遇到了问题。

基本上我所有的实体都是 Table<TEntity> 类型在我的上下文类(class)中。例如我有 Table<User>Table<Calendar>

当我为存储库行为构建各种接口(interface)时,我意识到有些方法对于每个实体来说都是非常冗余的。例如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>'

隐式转换也不起作用。

有人曾经成功做过类似的事情吗?如果我必须让所有存储库类都实现相同的 findById 方法,其中包含完全相同的代码,那将是非常可悲的...我确信有一种方法可以不这样做,我只是找不到它。 :)

最佳答案

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

代码并不完全相同。在每种情况下,您都在上下文中引用不同的表。

我理解你的逻辑;你想要干燥。但拥有存储库的原因是让您能够通过注入(inject)模拟存储库而不是真实存储库来抽象数据访问逻辑,以促进单元测试。最实用(且灵活)的方法是保持表(和 DAL 对象)独立且不同。通过尝试泛化部分 DAL 对象,您将引入额外的耦合,这将使单元测试变得复杂。

关于c# - 通用表<TEntity>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1694851/

相关文章:

'all methods' 的 C# 委托(delegate)或 Func?

c# - Windows Phone 7 信息

c# - 在延迟加载的集合导航属性中调用 .Any() 会枚举该属性吗?

vb.net - 在 vb.Net 中实现继承的泛型接口(interface)

c# - Linq to SQL 不保存名为 'Value' 的属性

c# - 林克 "Could not translate expression... into SQL and could not treat it as a local expression."

c# - 使用 LinqDataSource 格式化问题的下拉列表

c# - 从对象数组中删除重复项

c# - 如何返回一个空的 IEnumerable?

java - 泛型中的嵌套扩展