如何使用LINQ to SQL创建通用的数据访问对象(DAO) CRUD方法

11

我是LINQ to SQL的新手,正在尝试创建一个通用的数据访问对象(DAO)来实现基本的Create、Read、Update和Destroy(CRUD)方法,以便可以重用代码。我成功地创建了一个通用方法,可以使用下面的代码删除任何实体,但我想知道是否有人知道如何创建一个通用方法,可以通过所有表上存在的公共Id字段选择任何实体。

    /// <summary>
    /// Generic method that deletes an entity of any type using LINQ
    /// </summary>
    /// <param name="entity"></param>
    /// <returns>bool indicating whether or not operation was successful</returns>
    public bool deleteEntity(Object entity)
    {
        try
        {
            DomainClassesDataContext db = new DomainClassesDataContext();
            db.GetTable(entity.GetType()).Attach(entity);
            db.GetTable(entity.GetType()).DeleteOnSubmit(entity);
            db.SubmitChanges();
            return true;
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
            return false;
        }
    }
我相信相同的模式将适用于更新和插入操作,并希望在GenericDAO中有一个通用方法,可以根据实体Id检索任何实体(例如客户,发票,工单等)。提前感谢您的回复。
1个回答

18
"I think you are looking for 仓储模式, the following is a simple implementation of it:
First you need to create an interface called IRepository like this:"
public interface IRepository<T> where T : class
{
    void Add(T entity);
    void Delete(T entity);
    void Update(T entity);
    IEnumerable<T> All();
    ...
}

然后:

public class Repository<T> : IRepository<T>
    where T : class, IEntity
{
    DataContext _db;
    public Repository()
    {
        _db = new DataContext("Database string connection");
        _db.DeferredLoadingEnabled = false;
    }
    public void Add(T entity)
    {
        if (!Exists(entity))
            GetTable.InsertOnSubmit(entity);
        else
            Update(entity);
        SaveAll();
    }
    public void Delete(T entity)
    {
        GetTable.DeleteOnSubmit(entity);
        SaveAll();
    }
    public void Update(T entity)
    {
        GetTable.Attach(entity, true);
        SaveAll();
    }
    System.Data.Linq.Table<T> GetTable
    {
        get { return _db.GetTable<T>(); }
    }
    public IEnumerable<T> All()
    {
        return GetTable;
    }
}

然后:
public class CustomerRepository : Repository<Customer>
{
    public ProductRepository()
        : base()
    {
    }
}

然后你可以像这样拥有一个类似的东西:
Customer newCustomer = new Customer { FistName = "Foo", LastName = "Boo" };
_customerRepository.Add(newCustomer);

当涉及到与数据库映射的实体时,Customer 是在 .dbml 中定义的。这只是一个开始,详细信息请参见以下内容:


非常感谢。这个完美地运作了。我过去只使用过Java中的Hibernate框架,而且框架已经就位。现在,我是一个独立开发者,从头开始开发项目,所以这是我第一次在团队之外编写自己的数据访问层。我希望我有足够的声望来投票支持这个解决方案。我是社区的新成员,当我的声望更高时,一定会投票支持它。 - Grasshopper
@MahmoudGamal 很好的回答。我们是否必须使用接口,而不能仅定义一个单一类(Repository),并从控制器的Action方法中添加、更新或删除记录呢?谢谢。 - Zaker
1
@用户 - 不是强制性的,但接口作为通用存储库工作,具有接口而不是直接使用类的优点,例如如果特定存储库需要额外操作,则可以扩展通用存储库接口。一般来说,这取决于您的设计和要求,还应了解更多关于类和接口以及何时选择其中之一的信息。 - Mahmoud Gamal
@MahmoudGamal 感谢您的回答,非常感谢您的帮助。我还有一个疑问,根据这个链接http://programmers.stackexchange.com/questions/180851/why-shouldnt-i-use-the-repository-pattern-with-entity-framework Entity Framework已经实现了存储库模式,那么如果是这种情况,我不能使用自己的存储库来减少编码吗?需要您的指导,感谢您的时间和耐心。 - Zaker
嗨@MahmoudGamal,感谢您的回答。有一件事让我困扰,因为GetTable()函数将检索整个表格,随着数据的增长,它不会变得越来越慢吗?谢谢。 - user2936719
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接