如何在实体框架6(代码优先)中调用存储过程?

 活宝贝aaaaaaaaaaaaa 发布于 2023-02-06 19:10

我是Entity Framework 6的新手,我想在我的项目中实现存储过程.我有一个存储过程如下:

ALTER PROCEDURE [dbo].[insert_department]
    @Name [varchar](100)
AS
BEGIN
    INSERT [dbo].[Departments]([Name])
    VALUES (@Name)

    DECLARE @DeptId int

    SELECT @DeptId = [DeptId]
    FROM [dbo].[Departments]
    WHERE @@ROWCOUNT > 0 AND [DeptId] = SCOPE_IDENTITY()

    SELECT t0.[DeptId]
    FROM [dbo].[Departments] AS t0
    WHERE @@ROWCOUNT > 0 AND t0.[DeptId] = @DeptId
END

Department 类:

public class Department
{
    public int DepartmentId { get; set; }       
    public string Name { get; set; }
}

modelBuilder 
.Entity() 
.MapToStoredProcedures(s => 
s.Update(u => u.HasName("modify_department") 
               .Parameter(b => b.Department, "department_id") 
               .Parameter(b => b.Name, "department_name")) 
 .Delete(d => d.HasName("delete_department") 
               .Parameter(b => b.DepartmentId, "department_id")) 
 .Insert(i => i.HasName("insert_department") 
               .Parameter(b => b.Name, "department_name")));

protected void btnSave_Click(object sender, EventArgs e)
{
    string department = txtDepartment.text.trim();

    // here I want to call the stored procedure to insert values
}

我的问题是:如何调用存储过程并将参数传递给它?

10 个回答
  • 您所要做的就是创建一个对象,该对象具有与存储过程返回的结果相同的属性名称.对于以下存储过程:

        CREATE PROCEDURE [dbo].[GetResultsForCampaign]  
        @ClientId int   
        AS
        BEGIN
        SET NOCOUNT ON;
    
        SELECT AgeGroup, Gender, Payout
        FROM IntegrationResult
        WHERE ClientId = @ClientId
        END
    

    创建一个类似于的类:

        public class ResultForCampaign
        {
            public string AgeGroup { get; set; }
    
            public string Gender { get; set; }
    
            public decimal Payout { get; set; }
        }
    

    然后通过执行以下操作调用该过程:

        using(var context = new DatabaseContext())
        {
                var clientIdParameter = new SqlParameter("@ClientId", 4);
    
                var result = context.Database
                    .SqlQuery<ResultForCampaign>("GetResultsForCampaign @ClientId", clientIdParameter)
                    .ToList();
        }
    

    结果将包含一个ResultForCampaign对象列表.您可以SqlQuery根据需要使用尽可能多的参数调用.

    2023-02-06 19:11 回答
  • 您可以DbContext按如下方式在类中调用存储过程.

    this.Database.SqlQuery<YourEntityType>("storedProcedureName",params);
    

    但是,如果您的存储过程返回多个结果集作为示例代码,那么您可以在MSDN上看到这篇有用的文章

    具有多个结果集的存储过程

    2023-02-06 19:11 回答
  • 您正在使用MapToStoredProcedures()它表示您正在将实体映射到存储过程,在执行此操作时,您需要放弃存储过程并使用context正常情况的事实.像这样的东西(写入浏览器所以未经测试)

    using(MyContext context = new MyContext())
    {
        Department department = new Department()
        {
            Name = txtDepartment.text.trim()
        };
        context.Set<Department>().Add(department);
    }
    

    如果你真正想要做的就是直接调用存储过程然后使用 SqlQuery

    2023-02-06 19:12 回答
  • object[] xparams = {
                new SqlParameter("@ParametterWithNummvalue", DBNull.Value),
                new SqlParameter("@In_Parameter", "Value"),
                new SqlParameter("@Out_Parameter", SqlDbType.Int) {Direction = ParameterDirection.Output}};
    
            YourDbContext.Database.ExecuteSqlCommand("exec StoreProcedure_Name @ParametterWithNummvalue, @In_Parameter, @Out_Parameter", xparams);
            var ReturnValue = ((SqlParameter)params[2]).Value;  
    

    2023-02-06 19:12 回答
  • 我用它解决了 ExecuteSqlCommand

    把你自己的方法像我一样在DbContext中作为你自己的实例:

    public void addmessage(<yourEntity> _msg)
    {
        var date = new SqlParameter("@date", _msg.MDate);
        var subject = new SqlParameter("@subject", _msg.MSubject);
        var body = new SqlParameter("@body", _msg.MBody);
        var fid = new SqlParameter("@fid", _msg.FID);
        this.Database.ExecuteSqlCommand("exec messageinsert @Date , @Subject , @Body , @Fid", date,subject,body,fid);
    }
    

    所以你可以在你的代码隐藏中使用这样的方法:

    [WebMethod] //this method is static and i use web method because i call this method from client side
    public static void AddMessage(string Date, string Subject, string Body, string Follower, string Department)
    {
        try
        {
            using (DBContext reposit = new DBContext())
            {
                msge <yourEntity> Newmsg = new msge();
                Newmsg.MDate = Date;
                Newmsg.MSubject = Subject.Trim();
                Newmsg.MBody = Body.Trim();
                Newmsg.FID= 5;
                reposit.addmessage(Newmsg);
            }
        }
        catch (Exception)
        {
            throw;
        }
    }
    

    这是我的SP:

    Create PROCEDURE dbo.MessageInsert
    
        @Date nchar["size"],
        @Subject nchar["size"],
        @Body nchar["size"],
        @Fid int
    AS
        insert into Msg (MDate,MSubject,MBody,FID) values (@Date,@Subject,@Body,@Fid)
        RETURN
    

    希望能帮助你

    2023-02-06 19:12 回答
  • 您现在还可以使用我创建的约定,该约定允许从EF本地调用存储过程(包括返回多个结果集的存储过程),TVF和标量UDF.

    在实体框架6.1发布之前,只有在执行数据库优先时,才能在EF中使用存储功能(即表值函数和存储过程).有一些解决方法可以在Code First应用程序中调用商店功能,但您仍然无法在Linq查询中使用TVF,这是最大的限制之一.在EF 6.1中,映射API被公开(随着一些额外的调整)使得在Code First应用程序中使用商店功能成为可能.

    阅读更多

    在过去的两周里,我非常努力地推出了这个约定的beta版本,它允许在使用Code First方法和Entity Framework 6.1.1的应用程序中使用存储函数(即存储过程,表值函数等)(或更新).我对此版本中包含的修复程序和新功能非常满意.

    阅读更多.

    2023-02-06 19:12 回答
  • 看一下这个链接,该链接显示了EF 6与存储过程的映射如何进行插入,更新和删除:http://msdn.microsoft.com/en-us/data/dn468673

    加成

    以下是从Code First调用存储过程的一个很好的示例:

    假设您必须使用单个参数执行存储过程,并且存储过程返回一组与实体状态匹配的数据,因此我们将具有:

    var countryIso = "AR"; //Argentina
    
    var statesFromArgentina = context.Countries.SqlQuery(
                                          "dbo.GetStatesFromCountry @p0", countryIso
                                                        );
    

    现在让我们说我们要用两个参数执行另一个存储过程:

    var countryIso = "AR"; //Argentina
    var stateIso = "RN"; //Río Negro
    
    var citiesFromRioNegro = context.States.SqlQuery(
                                "dbo.GetCitiesFromState @p0, @p1", countryIso, stateIso
                              );
    

    请注意,我们正在使用基于索引的参数命名.这是因为实体框架将这些参数作为DbParameter对象包装起来,以避免任何SQL注入问题.

    希望这个例子有帮助!

    2023-02-06 19:12 回答
  • 这通过在传入参数时从存储过程中拉回数据来为我工作.

    var param = new SqlParameter("@datetime", combinedTime);
    var result = 
            _db.Database.SqlQuery<QAList>("dbo.GetQAListByDateTime @datetime", param).ToList();
    

    _db 是dbContext

    2023-02-06 19:12 回答
  • public IList<Models.StandardRecipeDetail> GetRequisitionDetailBySearchCriteria(Guid subGroupItemId, Guid groupItemId)
    {
        var query = this.UnitOfWork.Context.Database.SqlQuery<Models.StandardRecipeDetail>("SP_GetRequisitionDetailBySearchCriteria @SubGroupItemId,@GroupItemId",
        new System.Data.SqlClient.SqlParameter("@SubGroupItemId", subGroupItemId),
        new System.Data.SqlClient.SqlParameter("@GroupItemId", groupItemId));
        return query.ToList();
    }
    

    2023-02-06 19:12 回答
  • 使用您的示例,有两种方法可以实现此目的:

    1 - 使用存储过程映射

    请注意,此代码可以使用或不使用映射.如果关闭实体上的映射,EF将生成insert + select语句.

    protected void btnSave_Click(object sender, EventArgs e)
    {
         using (var db = DepartmentContext() )
         {
            var department = new Department();
    
            department.Name = txtDepartment.text.trim();
    
            db.Departments.add(department);
            db.SaveChanges();
    
            // EF will populate department.DepartmentId
            int departmentID = department.DepartmentId;
         }
    }
    

    2 - 直接调用存储过程

    protected void btnSave_Click(object sender, EventArgs e)
    {
         using (var db = DepartmentContext() )
         {
            var name = new SqlParameter("@name", txtDepartment.text.trim());
    
            //to get this to work, you will need to change your select inside dbo.insert_department to include name in the resultset
            var department = db.Database.SqlQuery<Department>("dbo.insert_department @name", name).SingleOrDefault();
    
           //alternately, you can invoke SqlQuery on the DbSet itself:
           //var department = db.Departments.SqlQuery("dbo.insert_department @name", name).SingleOrDefault();
    
            int departmentID = department.DepartmentId;
         }
    }
    

    我建议使用第一种方法,因为您可以直接使用department对象而不必创建一堆SqlParameter对象.

    2023-02-06 19:14 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有