2013-01-10 27 views
31

我已经从MySQL数据库生成了EF4模型,并且包含了StoredProcedures和Tables。如何使用EntityFramework调用存储过程?

我知道如何定期对EF进行instert/update/fetch/delete操作,但是找不到我的StoredProcedures。

这正是我所期待的:

using (Entities context = new Entities()) 
{ 
    context.MyStoreadProcedure(Parameters); 
} 

编辑1:

这是如何看起来不EF:

sqlStr = "CALL updateGame(?,?,?,?,?,?,?)"; 

commandObj = new OdbcCommand(sqlStr, mainConnection); 
commandObj.Parameters.Add("@id,", OdbcType.Int).Value = inGame.id; 
commandObj.Parameters.Add("@name", OdbcType.VarChar, 255).Value = inGame.name; 
commandObj.Parameters.Add("@description", OdbcType.Text).Value = ""; //inGame.description; 
commandObj.Parameters.Add("@yearPublished", OdbcType.DateTime).Value = inGame.yearPublished; 
commandObj.Parameters.Add("@minPlayers", OdbcType.Int).Value = inGame.minPlayers; 
commandObj.Parameters.Add("@maxPlayers", OdbcType.Int).Value = inGame.maxPlayers; 
commandObj.Parameters.Add("@playingTime", OdbcType.VarChar, 127).Value = inGame.playingTime;  

return Convert.ToInt32(executeScaler(commandObj)); 

PS。如果需要的话我可以改变EF版本

编辑1:

CREATE DEFINER=`106228`@`%` PROCEDURE `updateGame`(
    inId INT, 
    inName VARCHAR(255), 
    inDescription TEXT, 
    inYearPublished DATETIME, 
    inMinPlayers INT, 
    inMaxPlayers INT, 
    inPlayingTime VARCHAR(127) 
) 

回答

0

这是我最近做了具有2008 SQL数据库我的数据可视化应用程序。在这个例子中,我recieving从一个存储过程返回一个列表:

public List<CumulativeInstrumentsDataRow> GetCumulativeInstrumentLogs(RunLogFilter filter) 
    { 
     EFDbContext db = new EFDbContext(); 
     if (filter.SystemFullName == string.Empty) 
     { 
      filter.SystemFullName = null; 
     } 
     if (filter.Reconciled == null) 
     { 
      filter.Reconciled = 1; 
     } 
     string sql = GetRunLogFilterSQLString("[dbo].[rm_sp_GetCumulativeInstrumentLogs]", filter); 
     return db.Database.SqlQuery<CumulativeInstrumentsDataRow>(sql).ToList(); 
    } 

,然后在我的情况下,一些格式此扩展方法:

public string GetRunLogFilterSQLString(string procedureName, RunLogFilter filter) 
     { 
      return string.Format("EXEC {0} {1},{2}, {3}, {4}", procedureName, filter.SystemFullName == null ? "null" : "\'" + filter.SystemFullName + "\'", filter.MinimumDate == null ? "null" : "\'" + filter.MinimumDate.Value + "\'", filter.MaximumDate == null ? "null" : "\'" + filter.MaximumDate.Value + "\'", +filter.Reconciled == null ? "null" : "\'" + filter.Reconciled + "\'"); 

     } 
+0

我不明白,为什么我应该对SP名称进行硬编码?我在生成模型时添加了它们?应该不只是在Context对象上的某个地方作为方法? – Ivy

-1

阅读优秀的文章(以及相关视频)由朱莉勒曼(编程实体框架的作者)

Stored Procedures in the Entity Framework

+1

刚刚运行一个简单的StoredProcedure的文本很多,感觉EF已经或多或少地忘记了SP?为什么不把上下文对象当作方法?在模型生成过程中添加了Thay? – Ivy

+0

这是设计。上下文对象只是'ObjectSet '。是的,玩SP与和IQueryable玩不一样 – Tilak

+0

这就是为什么我们不鼓励只有链接的帖子....现在链接到实体框架主页。 – saluce

57

的一种方法是使用数据库属性关闭的DbContext:

SqlParameter param1 = new SqlParameter("@firstName", "Frank"); 
SqlParameter param2 = new SqlParameter("@lastName", "Borland"); 
context.Database.ExecuteSqlCommand("sp_MyStoredProc @firstName, @lastName", 
           param1, param2); 

EF5肯定支持。

+0

我没有明白,为什么我应该对SP名称进行硬编码?我在生成模型时添加了它们?应该不只是在Context对象上的某个地方作为方法? – Ivy

+1

是的,如果你没有将它链接到你的模型,并且你想要_raw_访问,这就是它的方法;) –

+1

这只是执行存储过程作为非查询。它无法读取任何返回的表 – 2016-10-13 06:31:20

4

将存储过程导入到模型中之后,可以右键单击(从模型浏览器的Context.Store/Stored Procedures部分),然后单击Add Function Import。如果你需要一个复杂的类型,你可以在那里创建它。

+0

尝试过,但它不会生成带参数的方法?不知道如何推入参数? – Ivy

+1

当过程有参数时,它们将被添加。 – user1908061

+0

不,它不? – Ivy

8

您已使用SqlQuery函数并指示实体来映射结果。

我送一个例子来执行此:

var oficio= new SqlParameter 
{ 
    ParameterName = "pOficio", 
    Value = "0001" 
}; 

using (var dc = new PCMContext()) 
{ 
    return dc.Database 
      .SqlQuery<ProyectoReporte>("exec SP_GET_REPORTE @pOficio", 
             oficio) 
      .ToList(); 
} 
+0

您必须声明代表查询返回的结果表的ProyectoReporte类 – 2016-10-13 06:32:21

0

基本上你只需要映射的方法,使用存储过程映射的实体。

一旦映射完成,您将使用常规方法在EF中添加项目,并使用您的存储过程。

请参阅:This Link进行演练。 结果将增加基于了OP的原始请求,以便能够像这样调用一个存储过程,像这样的实体(这将实际使用存储过程)

using (var ctx = new SchoolDBEntities()) 
     { 
      Student stud = new Student(); 
      stud.StudentName = "New sp student"; 
      stud.StandardId = 262; 

      ctx.Students.Add(stud); 
      ctx.SaveChanges(); 
     } 
1

...

using (Entities context = new Entities()) 
{ 
    context.MyStoreadProcedure(Parameters); 
} 

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

...和我工作的一个stored procedure frameworkhere)的你可以打电话像我在下面显示的测试方法之一...

[TestClass] 
public class TenantDataBasedTests : BaseIntegrationTest 
{ 
    [TestMethod] 
    public void GetTenantForName_ReturnsOneRecord() 
    { 
     // ARRANGE 
     const int expectedCount = 1; 
     const string expectedName = "Me"; 

     // Build the paraemeters object 
     var parameters = new GetTenantForTenantNameParameters 
     { 
      TenantName = expectedName 
     }; 

     // get an instance of the stored procedure passing the parameters 
     var procedure = new GetTenantForTenantNameProcedure(parameters); 

     // Initialise the procedure name and schema from procedure attributes 
     procedure.InitializeFromAttributes(); 

     // Add some tenants to context so we have something for the procedure to return! 
     AddTenentsToContext(Context); 

     // ACT 
     // Get the results by calling the stored procedure from the context extention method 
     var results = Context.ExecuteStoredProcedure(procedure); 

     // ASSERT 
     Assert.AreEqual(expectedCount, results.Count); 
    } 
} 

internal class GetTenantForTenantNameParameters 
{ 
    [Name("TenantName")] 
    [Size(100)] 
    [ParameterDbType(SqlDbType.VarChar)] 
    public string TenantName { get; set; } 
} 

[Schema("app")] 
[Name("Tenant_GetForTenantName")] 
internal class GetTenantForTenantNameProcedure 
    : StoredProcedureBase<TenantResultRow, GetTenantForTenantNameParameters> 
{ 
    public GetTenantForTenantNameProcedure(
     GetTenantForTenantNameParameters parameters) 
     : base(parameters) 
    { 
    } 
} 

如果这两种方法中的任何一种都有什么好处?