我对实体框架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

系类:

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

modelBuilder 
.Entity<Department>() 
.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
}

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


当前回答

看一下这个链接,它展示了如何将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注入问题。

希望这个例子能有所帮助!

其他回答

当EDMX创建时,如果你在表选择选项中选择存储过程,那么只需使用过程名调用存储过程…

var num1 = 1; 
var num2 = 2; 

var result = context.proc_name(num1,num2).tolist();// list or single you get here.. using same thing you can call insert,update or delete procedured.

minddless passenger有一个项目,允许使用实体框架从存储过程中返回多个结果集。下面是他的一个例子....

using (testentities te = new testentities())
{
    //-------------------------------------------------------------
    // Simple stored proc
    //-------------------------------------------------------------
    var parms1 = new testone() { inparm = "abcd" };
    var results1 = te.CallStoredProc<testone>(te.testoneproc, parms1);
    var r1 = results1.ToList<TestOneResultSet>();
}

用你的例子,这里有两种方法来实现这一点:

方法#1:使用存储过程映射

请注意,这段代码可以使用映射,也可以不使用映射。如果在实体上关闭映射,EF将生成一个插入+选择语句。

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对象。

这是EF (DB first)在DbContext类中生成的:

public ObjectResult<int> Insert_Department(string department)
{
    var departmentParameter = new ObjectParameter("department", department);

    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<int>("insert_department", departmentParameter);
}

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

    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。