Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 如何使用存储过程&x2B;存储库&x2B;实体框架中的工作单元模式?_Entity Framework_Entity Framework 4_Ef Code First_Repository Pattern_Unit Of Work - Fatal编程技术网

Entity framework 如何使用存储过程&x2B;存储库&x2B;实体框架中的工作单元模式?

Entity framework 如何使用存储过程&x2B;存储库&x2B;实体框架中的工作单元模式?,entity-framework,entity-framework-4,ef-code-first,repository-pattern,unit-of-work,Entity Framework,Entity Framework 4,Ef Code First,Repository Pattern,Unit Of Work,我有MVCWeb应用程序项目,首先是实体框架代码。在这个项目中,我将使用通用存储库和工作单元模式。另外,我还想使用存储过程来实现get list by和get list方法 如何将存储过程与通用存储库和工作单元模式一起使用?添加到您的通用存储库中 public IEnumerable<T> ExecWithStoreProcedure(string query, params object[] parameters) { return _context.Databas

我有MVCWeb应用程序项目,首先是实体框架代码。在这个项目中,我将使用通用存储库和工作单元模式。另外,我还想使用存储过程来实现get list by和
get list
方法


如何将存储过程与通用存储库和工作单元模式一起使用?

添加到您的通用存储库中

public IEnumerable<T> ExecWithStoreProcedure(string query, params object[] parameters)
{
        return _context.Database.SqlQuery<T>(query, parameters);
}
public IEnumerable可执行存储过程(字符串查询,参数对象[]参数)
{
返回_context.Database.SqlQuery(查询,参数);
}
然后您可以使用任何unitofwork/repository调用它,如

IEnumerable<Products> products = 
             _unitOfWork.ProductRepository.ExecWithStoreProcedure(
             "spGetProducts @bigCategoryId",
             new SqlParameter("bigCategoryId", SqlDbType.BigInt) { Value = categoryId } 
      );
IEnumerable产品=
_unitOfWork.ProductRepository.ExecWithStoreProcedure(
“spGetProducts@bigCategoryId”,
新的SqlParameter(“bigCategoryId”,SqlDbType.BigInt){Value=categoryId}
);

您不应该尝试将SPs与UoW/存储库模式一起使用,因为它们在代码中很难控制,并且通常不会映射回相同的实体类型。UoW和Repository模式更适合直接使用ADO.NET而不是实体框架,因为EF已经是一种存储库模式了。我建议在使用SPs时,CQR是一种更好的模式。在详细说明@sunil的答案和我对它的评论后,我创建了一个专门用于处理存储过程的类。模拟和测试也很容易

public class ProcedureManager : IProcedureManager
{
    internal DbContext Context;

    public ProcedureManager(DbContext context)
    {
        Context = context;
    }

    //When you expect a model back (async)
    public async Task<IList<T>> ExecWithStoreProcedureAsync<T>(string query, params object[] parameters)
    {
        return await Context.Database.SqlQuery<T>(query, parameters).ToListAsync();
    }

    //When you expect a model back
    public IEnumerable<T> ExecWithStoreProcedure<T>(string query)
    {
        return Context.Database.SqlQuery<T>(query);
    }

    // Fire and forget (async)
    public async Task ExecuteWithStoreProcedureAsync(string query, params object[] parameters)
    {
        await Context.Database.ExecuteSqlCommandAsync(query, parameters);
    }

    // Fire and forget
    public void ExecuteWithStoreProcedure(string query, params object[] parameters)
    {
        Context.Database.ExecuteSqlCommand(query, parameters);
    }
}
公共类过程管理器:IProcedureManager
{
内部语境;
公共过程管理器(DbContext上下文)
{
上下文=上下文;
}
//当您希望模型返回时(异步)
公共异步任务ExecWithStoreProcedureAsync(字符串查询,参数对象[]参数)
{
返回wait Context.Database.SqlQuery(query,parameters.toListSync();
}
//当你期待一个模特回来的时候
公共IEnumerable可执行存储过程(字符串查询)
{
返回Context.Database.SqlQuery(查询);
}
//触发并忘记(异步)
公共异步任务ExecuteWithStoreProcedureAsync(字符串查询,参数对象[]参数)
{
wait Context.Database.ExecuteSqlCommandAsync(查询,参数);
}
//开火然后忘记
public void ExecuteWithStoreProcedure(字符串查询,参数对象[]参数)
{
Context.Database.ExecuteSqlCommand(查询、参数);
}
}

对于通用存储库,添加以下内容:

  public IEnumerable<TEntity> GetdataFromSqlcommand(string command, System.Data.SqlClient.SqlParameter[] parameter)
    {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.Append($"EXECUTE {command}");
        strBuilder.Append(string.Join(",", parameter.ToList().Select(s => $" @{s.ParameterName}")));

        return Context.Set<TEntity>().FromSql(strBuilder.ToString(), parameter);
    }
公共IEnumerable GetdataFromSqlcommand(字符串命令,System.Data.SqlClient.SqlParameter[]参数) { StringBuilder strBuilder=新StringBuilder(); 追加($“执行{command}”); strBuilder.Append(string.Join(“,”,parameter.ToList().Select(s=>$”@{s.ParameterName})); 返回Context.Set().FromSql(strBuilder.ToString(),参数); } 您只需要发送存储过程名称和参数数组:

public IEnumerable<MainData> GetMainData(Param query)
{
    var param1 = new SqlParameter("param1", query.param1);
    var param2 = new SqlParameter("param2", query.param2);
    return GetdataFromSqlcommand("StoredProcedurename", parameter: new[] { param1, param2 }).ToList();
}
public IEnumerable GetMainData(参数查询)
{
var param1=新的SqlParameter(“param1”,query.param1);
var param2=新的SqlParameter(“param2”,query.param2);
返回GetdataFromSqlcommand(“StoredProcedurename”,参数:new[]{param1,param2}).ToList();
}

如果您使用的是.net core 3.1,则必须解决此问题

  • 您将创建一个包含存储过程结果的类

  • 您将从DBcontext创建另一个分部类,并将上一个类放入其中

  • 您将创建
    IStoredProcedure
    接口,并使用泛型在存储过程中实现它

  • 在启动类中注入存储过程类

  • 不要忘记使结果类字段与结果表单存储过程相同

  • 执行存储过程

  • 实施:

    (1)第一步

    public class TaskPercents
    {
        public long Id { get; set; }
        public long SchoolRepId { get; set; }
    
        public string Name { get; set; }
    }
    
    (2)第二步

    public partial class SchoolsPartnershipDBContext : DbContext
    {
        public virtual DbSet<TaskPercents> TaskPercents { get; set; }
    }
    

    代码优先的方法目前还不支持使用存储过程——这是EntityFrameworkV6中即将推出的一项功能,预计将在今年晚些时候推出year@marc_s:准确地说,它不支持将存储过程映射到.NET方法。使用它们并将对
    SqlQuery
    (使用SP name作为参数)的调用包装到存储库方法中是可能的()。不是完美的方法,但可能…@Slauma-实际上,我想你的意思是它不支持将EF模型映射到存储过程。这在v6中得到了解决。您可以将存储的过程映射到对象,也可以将存储过程映射到方法(即包装它)。但这在很大程度上首先是一个手工编写代码的过程。@marc_s我用谷歌搜索了一下,但我找不到任何使用存储过程的示例,感谢您的编辑和帮助comment@marc_s为什么你说的不是完美的方法?你有什么理由吗?谢谢你的回答,但在你回答的第二部分中有一个问题,我们在genric repository我认为通过使用工作单元,我必须这样说_unitOfWork.ProductRepository.ExecuteStoreProcedure(我们的查询,parametrs[]);如果我认为错了peleas说你是对的,那么应该是
    \u unitOfWork.ProductRepository.ExecWithStoreProcedure
    T将来自
    ProductRepository:genericrerepository
    ,但是如果你的SP没有返回存储库映射到的实体,该怎么办?例如,我的SP可能返回连接表的数据,或者只返回一个名为“Result”的整数值。在这种情况下,对产品实体使用上述示例将是不够的,并且会打破接口隔离原则。有什么想法吗?想看看上面的命令是否有响应这只是调用一个存储过程,它不会遵守UOW。这只是调用一个存储过程,它不会遵守UOW。当然不会。SPs不能遵循UoW模式,因为UoW模式适用于跟踪更改和按照的ORM
    public interface IStoredProcedure<T> 
    {
        public List<T> ExecuteStored(string query);
    }
    
    {
        private SchoolsPartnershipDBContext _context;
    
        public StoredProcedure(SchoolsPartnershipDBContext Context)
        {
            _context = Context;
        }
    
        public List<T> ExecuteStored(string query)
        {
            //Context = new SchoolsPartnershipDBContext();
            var r = _context.Set<T>().FromSqlRaw(query);
            return r.ToList();
            // return null;
        }
    }
    
            var result = _storedProcedure.ExecuteStored("TaskExecPercentForSchoolRep");
            return result.ToList();