【问题标题】:Design of Data Access Layer using Repository without using Entity Framework使用 Repository 不使用实体框架设计数据访问层
【发布时间】:2017-10-20 09:07:42
【问题描述】:

我正在开发一个 n 层应用程序,我决定在数据访问层使用存储库模式,但我不想使用任何 ORM(打算使用 ADO.net)

我无法决定如何在两个实体之间存在关系(不是父子关系)的存储库中获取数据。 例如我有客户和订单表。 “订单”表中有“客户ID”列,链接到“客户”表。

  1. 在获取订单时如何获取客户信息
    基于 OrderID 的信息(单个或多个)?
  2. 我们可以将一个存储库的创建实例用于另一个存储库吗?

下面是当前的代码结构。

///////////// Abstract Class for Common Functionality////
public abstract class BaseRepository<T> where T : class
{
    private static SqlConnection sqlConnection;
    protected string DatabaseName { get; set; }
    protected string ConnectionString;
    public delegate T CallBack(SqlDataReader reader);

    public BaseRepository()
    {
        ConnectionString = Convert.ToString(ConfigurationManager.ConnectionStrings["TestDB"]);
        sqlConnection = new SqlConnection(ConnectionString);
    }

    protected abstract T PopulateRecord(SqlDataReader reader);

    protected IEnumerable<T> GetRecords(SqlCommand command)
    {
        var list = new List<T>();
        using (SqlConnection connection = new SqlConnection(ConnectionString))
        {
            command.Connection = connection;
            connection.Open();

            using (SqlDataReader reader = command.ExecuteReader())
            {
                if (reader != null)
                {
                    while (reader.Read())
                    {
                        list.Add(PopulateRecord(reader));
                    }
                }
            } // reader closed and disposed up here
        } //connection closed and disposed here
        return list;
    }

}

////////////////// Repository Class //////////////////////////

public class OrderRepository : BaseRepository<Order>, IRepository<Order>
{
    protected override Order PopulateRecord(SqlDataReader reader)
    {
        return new Order
        {
            OrderID = reader.GetIntVal("OrderID"),
            OrderDate = reader.GetDateTimeVal("OrderDate"),
            ProductInfo= // How to Populate Product Information which is in another repository
            CustomerInfo = // How to Populate Customer Information which is in another repository
        };
    }

    public IEnumerable<Order> GetAll()
    {
        SqlCommand cmd = new SqlCommand();
        cmd.CommandText = "GetOrders";
        cmd.CommandType = CommandType.StoredProcedure;
        return GetRecords(cmd);

    }

}

/////////////// Entity Class ////////////////////
public class Order {

    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public Customer ProductInfo { get; set; }
    public Product CustomerInfo { get; set; }
}

public class Customer {

    public int CustomerID { get; set; }
    public string CustomerName { get; set; }
}

public class Product {

    public int ProductID { get; set; }
    public string ProductName { get; set; }
}

【问题讨论】:

  • 你用什么来代替“任何 ORM”?应用正确的标签。在问题中发布(部分)内联代码,这些链接会在一段时间后失效。

标签: c# ado.net repository-pattern data-access-layer


【解决方案1】:

我和一位前同事创建了实现存储库模式的 SqlRepo。

从注入的工厂获得存储库后,您可以创建一个命令并使用流畅的 API 和表达式构建查询,然后再执行它以返回实体。

尽管单元测试本身就形成了很好的文档,但它仍然是一项仍在进行中的工作,文档很少,但很乐意回答问题。

看看http://github.com/testpossessed/sqlrepo

更新:例如,您的问题的解决方案是这样的(假设工厂是私有字段,通常注入):

var customerRepository = this.repositoryFactory.Create<Customer>();
var customer = customerRepository.Query()
                                 .Where(e => e.Id == 123)
                                 .Go();

var orderRepository = this.repositoryFactory.Create<Order>();
customer.Orders = orderRepository.Query()
                                 .Where(e => e.CustomerId == 123)
                                 .Go();

【讨论】:

  • 你能告诉我上面写的代码应该放在存储库还是业务层?(顺便说一下,我使用普通的 ADO.net 来访问数据)。
  • 我猜你会说业务层。我通常实现包含此代码的 UnitOfWork 组件,然后将它们注入到其他组件中,例如控制器或视图模型
  • 我想在存储库本身中填充我的域对象。
  • 目前我们没有嵌套集合的实体映射。这是我们想要添加但尚未添加的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
  • 2011-07-15
  • 2016-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多