2013-01-10 58 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) 
    { 
    } 
} 

如果這兩種方法中的任何一種都有什麼好處?