【问题标题】:Using Generic Repository and Stored Procedures使用通用存储库和存储过程
【发布时间】:2015-01-15 22:20:25
【问题描述】:

我正在开发一个现有的应用程序,它首先使用 Generic Repo 模式和 EF6 数据库。 我正在调用一个存储过程,它返回一个复杂类型,该类型在我的实体模型中不是现有实体,因此我不确定要给出什么类型。

这是从我的服务层调用我的 sp 的方式

_unitOfWork.Repository<Model>()
            .SqlQuery("sp_Get @FromDateTime, @ToDateTime, @CountyId",
                         new SqlParameter("FromDateTime", SqlDbType.DateTime) { Value = Request.FromDateTime },
                         new SqlParameter("ToDateTime", SqlDbType.DateTime) { Value = Request.TripToDateTime },
                         new SqlParameter("CountyId", SqlDbType.Int) { Value = Convert.ToInt32(Request.County) }
           ).ToList();

我是否在我的数据层中创建一个实体以映射到,或者存储过程返回复杂类型的最佳方法是什么。 如果是这样,是否需要自定义映射,或者只是创建实体类的一种情况

谢谢

【问题讨论】:

    标签: c# entity-framework stored-procedures ddd-repositories


    【解决方案1】:

    如果你有一个包含这些字段的实体,你可以像上面显示的那样调用 SqlQuery 方法,如果没有,那么我建议创建一个新类来映射结果:

    public class Result
    {
        public int CountyId { get; set; }
    
        public DateTime FromDateTime { get; set; }
    
        public DateTime ToDateTime { get; set; }
    }
    

    我不知道在您的情况下如何实现 UnitOfWork 模式,但我假设您可以访问您的上下文。在您的 UnitOfWork 类中,您可以创建一个像这样的通用方法:

    public class UnitOfWork 
    {
        private YourContext Context { get; set; }
    
        public DbRawSqlQuery<T> SQLQuery<T>(string sql, params object[] parameters)
        {
           return Context.Database.SqlQuery<T>(sql, parameters);
        }
    }
    

    这样,您可以执行如下所示的存储过程:

    var result= _unitOfWork.SqlQuery<Result>("sp_Get @FromDateTime, @ToDateTime, @CountyId",
                         new SqlParameter("FromDateTime", SqlDbType.DateTime) { Value = Request.FromDateTime },
                         new SqlParameter("ToDateTime", SqlDbType.DateTime) { Value = Request.TripToDateTime },
                         new SqlParameter("CountyId", SqlDbType.Int) { Value = Convert.ToInt32(Request.County) }
           ).ToList();
    

    【讨论】:

    • 这种方法对我有用。我还必须将我的新类/实体添加到我的上下文类中。 public DbSet&lt;ModelType&gt; modelName { get; set; } 我必须确保我的新实体有一个 [key] 并继承自 EntityBase
    【解决方案2】:

    Repository Pattern 的目的是抽象出数据的存储和检索以保护您的客户端代码,例如业务层(在您的情况下为服务层)无需了解有关数据如何持久化的任何信息。例如,SQL 语句将只存在于您的 Repository 类中,而不会影响您的代码。

    如果您将 SQL、存储过程名称和参数暴露给您的客户端代码,您将不会从存储库模式中获得太多好处,而且实际上您根本不能真正将其称为存储库。您失去了能够独立于数据访问层模拟存储库和测试业务层的好处。这意味着需要集成测试(需要完整的数据库实例)来验证业务逻辑。

    考虑重构,以便拥有一个 CountryRepository 类,该类具有返回 Country 实体或类似实体的 GetCountry(int CountryId, DateTime fromDate, DateTime toDate) 方法。我想您会同意,与您问题中的代码相比,您的代码的可读性会大大提高。

    public class CountryRepository
    {
      public Country GetCountry(int CountryId, DateTime fromDate, DateTime toDate)
      {
        // EF or ADO.NET code here
      }
    }
    

    然后客户端代码将是例如

    var c = unitOfWork.CountryRepository.GetCountry(1, DateTime.Now.AddYears(-1), DateTime.Now);
    

    另请参阅SO question

    【讨论】:

      【解决方案3】:
      public virtual IEnumerable<T> GetWithRawSql(string query, params object[] parameters)
              {
                  return DbSet.SqlQuery(query, parameters).ToList();
              }
      

      界面

      IEnumerable<T> GetWithRawSql(string query, params object[] parameters);
      

      【讨论】:

      • 他先使用数据库,没有DbContext,没有DbSet
      【解决方案4】:
          IQueryable<Cm_Customer> customerQuery = _uow.SqlQuery<Cm_Customer>(@" DECLARE @UserId INT = {0}
                                                     EXEC Cm_GetCustomersByUserId @UserId", filter.UserId).AsQueryable();
          IQueryable<Cm_Customer> custs = customerQuery.IncludeMultiple(k => k.Cm_CustomerLocations,
                                                 k => k.Cm_CustomerSalesmans,
                                                 k => k.Cm_CustomerMachineparks,
                                                 k => k.Cm_CustomerAuthenticators,
                                                 k => k.Cm_CustomerInterviews,
                                                 k => k.Cm_CustomerRequest,
                                                 k => k.Cm_MachineparkRental).AsQueryable();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-06
        • 2020-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多