将我的DAL代码重新分解为域驱动设计或更现代的设计(C#3.5)?

Cha*_*aka 5 architecture asp.net data-access-layer repository

该开发仅限于Visual Studio 2010(客户端批准的软件).我们需要通过存储过程访问数据.我想避免让它过于复杂而且时间紧迫.我看到的大多数设计涉及EF和LINQ,不确定如何设计procs?

我想创建一个单独的代码库项目(使用Web UI):

Application.Domain
      -  Interact get/put stored procedures, entities

Application.Web
      - containing Web UI (JQuery, AJAX), WCF Service
Run Code Online (Sandbox Code Playgroud)

谁能给我一些关于如何处理Application.Domain的示例代码?

例子,我读过:

DAL\AppDAL.cs:

public static IEnumerable<TasCriteria> GetTasCriterias()
    {
        using (var conn = new SqlConnection(_connectionString))
        {
            var com = new SqlCommand();
            com.Connection = conn;
            com.CommandType = CommandType.StoredProcedure;

            com.CommandText = "IVOOARINVENTORY_GET_TASCRITERIA";
            var adapt = new SqlDataAdapter();
            adapt.SelectCommand = com;
            var dataset = new DataSet();
            adapt.Fill(dataset);

            var types = (from c in dataset.Tables[0].AsEnumerable()
                         select new TasCriteria()
                         {
                              TasCriteriaId = Convert.ToInt32(c["TasCriteriaId"]),
                              TasCriteriaDesc= c["CriteriaDesc"].ToString()
                         }).ToList<TasCriteria>();

            return types;
        }

    }
Run Code Online (Sandbox Code Playgroud)

型号\ TasCriteria.cs:

public class TasCriteria
    {
        public int TasCriteriaId { get; set; }
        public string TasCriteriaDesc { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

服务\ Service.svc:

 [OperationContract]
        [WebInvoke(ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.WrappedRequest, Method = "GET")]
        public List<TasCriteria> GetTasCriteriaLookup()
        {
            var tc = InventoryDAL.GetTasCriterias();
            return tc.ToList();
        }
Run Code Online (Sandbox Code Playgroud)

Ami*_*Ami 3

首先也是最重要的,确保使用依赖注入(例如 ninject 或 unity(或许多其他免费提供的)来抽象 DAL。很有可能你的 DAL 是松散耦合的,这样如果你稍后决定 EF(或任何其他 ORM)不是最好的方案,那么改变它不会花费太多精力......

您不希望有一个带有静态方法的 AppDAL 类来调用 SP。如果只是为了单元测试,至少添加一个接口并使用注入。

无论您使用 EF 还是 Nhibernate 还是任何其他 ORM,该决定都应该封装在您的 DAL 中,并且不会泄漏到其他层。域层应该使用来自 DAL 的存储库类的接口(并且这些类包含对所选 ORM 或数据访问类的引用)。

这些存储库将调用存储过程并返回您的模型类(POCO)。

在我最近的一个项目中,我们有这个接口来提供基本的 CRUD 操作:

public interface IRepository<T> where T : DomainEntity
{
    T Get(Int64 id);
    void SaveOrUpdate(T entity);
    void Delete(T entity);
    IQueryable<T> Find();
}
Run Code Online (Sandbox Code Playgroud)

DomainEntity 是一个非常简单的类,所有模型类都继承它。在极少数情况下,我们需要使用存储过程,我会创建一个额外的接口,提供 GetXXXEntity 方法(1 个或多个),这将执行对 SP 的实际调用。

所以,当我需要使用它的 ID 从数据库获取实体时,它看起来像:

_diWrapper.GetRepository<Person>().Get(id);
_diWrapper.GetRepository<Order>().Get(id);
Run Code Online (Sandbox Code Playgroud)

_diWrapper 是我的依赖注入容器(在本例中为 ninject)的包装器。我使用了包装器,因此如果需要,我可以轻松地用其他东西替换 ninject。

在我需要使用 linq 的常见情况下:

_diWrapper.GetRepository<Person>().Find().Where(q => q.Name == "Jack").ToList();
Run Code Online (Sandbox Code Playgroud)

重要的是我可以很快用其他东西取代 Nhibernate。

我强烈建议您查看 Fluent NHibernate,因为它提供了一个不需要太多编码的简单解决方案。

编辑:这是实现 IRepository 接口的存储库类的示例:

public class NhibernateRepository<T> : IRepository<T> where T : DomainEntity, new()
{
    private ISession _session;

    public NhibernateRepository()
    {
        _session = BaseNHibernateHelper<NHibernateHelper>.GetCurrentSession();
    }

    public T Get(Int64 id)
    {
        return _session.Get<T>(id);
    }

    public void SaveOrUpdate(T entity)
    {
        _session.SaveOrUpdate(entity);
    }

    public void Delete(T entity)
    {
        _session.Delete(entity);
    }

    public IQueryable<T> Find() 
    {
        return _session.Query<T>();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在构造函数中,我使用了我创建的另一个 nhibernate 助手来包装会话工厂。这就是我对 nhibernate 的依赖。

如果我想用另一种 ORM 替换 NH,我只需要修改存储库类(以及底层支持类),您可以看到 NH 不会泄漏到存储库类之外,并且使用它的人都不会意识到NH的使用。