如何调用entity framework6中的存储过程(代码优先)?

我对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<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 } 

我的问题是:我怎样才能调用存储过程并传递参数?

您可以按如下所示调用DbContext类中的存储过程。

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

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

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

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

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

创build一个如下所示的类:

  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

我用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) { int resault; try { using (DBContex reposit = new DBContex()) { 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 

希望对你有帮助

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

1 – 使用存储过程映射

请注意,此代码可以使用或不使用映射。 如果closures实体上的映射,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; } } 

我build议使用第一种方法,因为您可以直接使用部门对象,而不必创build一堆SqlParameter对象。

您现在也可以使用我创build的约定,它可以从EF原生地调用存储过程(包括返回多个结果集的存储过程),TVF和标量UDF。

在Entity Framework 6.1发布之前,只有在数据库优先的情况下,才可以在EF中使用存储函数(即Table Valued Functions和Stored Procedures)。 有一些解决方法可以在Code First应用程序中调用商店function,但是仍然无法在Linq查询中使用TVF,这是最大的限制之一。 在EF 6.1中,映射API被公开了(随着一些额外的调整),使得在Code First应用程序中使用存储function成为可能。

阅读更多

在过去的两个星期里,我非常努力地工作,在这里,这是公约的testing版本,它允许在使用Code First方法和entity framework6.1.1的应用程序中使用存储function(即存储过程,表值函数等)或更新)。 我对此版本中包含的修复和新function感到满意。

阅读更多 。

您正在使用MapToStoredProcedures() ,它表明您正在将您的实体映射到存储过程,当您这样做时,您需要放弃存在过程并正常使用context这一事实。 像这样( 写入浏览器,所以没有testing

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

如果你真的试图做的是直接调用存储过程,然后使用SqlQuery

看看这个链接,显示EF 6与存储过程的映射如何进行插入,更新和删除: http : //msdn.microsoft.com/zh-cn/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 ); 

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

希望这个例子有帮助!

 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; 

这对我来说,通过从参数中传回存储过程中的数据。

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

_db是dbContext

 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(); } 

无意识的乘客有一个项目,允许使用entity framework从存储过程返回多个结果集。 他下面的例子之一….

 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>(); } 

如果你想传递表参数到存储过程中,你必须为你的表参数设置TypeName属性。

 SqlParameter codesParam = new SqlParameter(CODES_PARAM, SqlDbType.Structured); SqlParameter factoriesParam = new SqlParameter(FACTORIES_PARAM, SqlDbType.Structured); codesParam.Value = tbCodes; codesParam.TypeName = "[dbo].[MES_CodesType]"; factoriesParam.Value = tbfactories; factoriesParam.TypeName = "[dbo].[MES_FactoriesType]"; var list = _context.Database.SqlQuery<MESGoodsRemain>($"{SP_NAME} {CODES_PARAM}, {FACTORIES_PARAM}" , new SqlParameter[] { codesParam, factoriesParam } ).ToList(); 

这是EF(DB首先)在DbContext类中生成的内容:

 public ObjectResult<int> Insert_Department(string department) { var departmentParameter = new ObjectParameter("department", department); return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<int>("insert_department", departmentParameter); }