2014-05-16 27 views
6

Ich verwende Entity Framework. Es gibt eine bestimmte Situation in meiner Anwendung, wo ich eine gespeicherte Prozedur verwenden muss. Da im SP viele SQL-Anweisungen geschrieben sind, möchte ich sie nicht in meinen C# -Code schreiben. Ich brauche nur das Ergebnis in Form einer Datentabelle zurück zu bekommen. Ich habe ein bisschen Code geschrieben, aber ich stecke an einem Punkt fest. Kann jemand den folgenden Code vervollständigen?Rückgabe Datentabelle mit Entity Framework

using (dbContext.Database.Connection) 
{ 
dbContext.Database.Connection.Open(); 
DbCommand cmdItems= dbContext.Database.Connection.CreateCommand(); 
cmdItems.CommandText = "GetAvailableItems"; 
cmdItems.CommandType = CommandType.StoredProcedure; 
cmdItems.Parameters.Add(new SqlParameter("jobCardId", 100525)); 
//Need to write code below to populate a DataTable. 
} 
+0

Verwendung erwähnten Link http://www.entityframeworktutorial.net/EntityFramework4.3/execute-stored-procedure-using-dbcontext .aspx –

+0

Ich verwende Code zuerst und ich habe keine Entität für das zurückgegebene Dataset. Ich brauche das Ergebnis als DataTable. Dort muss ich die dynamischen Daten bearbeiten (Daten mit unterschiedlichen Spaltennamen für den übergebenen Parameter). – user1640256

+0

@ user1640256 Ich sehe aus dem Code, dass Sie etwas aus der Datenbank "bekommen". Ich folge daraus, dass Sie eine SELECT-Abfrage durchführen. Sie wissen also recht gut, welche Spalten Sie aus der Datenbank holen. Können Sie einfach eine Entität erstellen und die Ergebnisse der gespeicherten Prozedur der Entität zuordnen? Das sollte deine Arbeit ziemlich einfach machen. –

Antwort

9

Vielen Dank Jungs. Ich habe es gelöst. Hier ist die Lösung:

using (var context = new DataBaseContext()) 
{ 
    var dt = new DataTable(); 
    var conn = context.Database.Connection; 
    var connectionState = conn.State; 
    try 
    { 
     if (connectionState != ConnectionState.Open) conn.Open(); 
     using (var cmd = conn.CreateCommand()) 
     { 
      cmd.CommandText = "GetAvailableItems"; 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add(new SqlParameter("jobCardId", 100525)); 
      using (var reader = cmd.ExecuteReader()) 
      { 
       dt.Load(reader); 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     // error handling 
     throw; 
    } 
    finally 
    { 
     if (connectionState != ConnectionState.Closed) conn.Close(); 
    } 
    return dt; 
} 
+1

Hier ist, warum ich das downvoted: Dies verwendet keine Entität in der Tat geht um Entität mit traditionellen SQL. Diese Fliege steht vor einer Entität, die den Zustand zwischen der Datenbank und den lokalen Daten beibehalten soll. –

+1

Es gibt jedoch Anwendungsfälle dafür ... Denk an eine Legacy-App, bei der die db wiederverwendet werden muss, aber neuer Code geschrieben wird (was ich gerade mache). EF kann an vielen Stellen verwendet werden, was das Leben viel einfacher macht, aber es gibt einige Legacy-Sprocs, die verschiedene Spalten zurückgeben (Pivoted-Tabellen). Keine Möglichkeit, dies einer Entität zuzuordnen, wenn Ihre Spaltennamen dynamisch sind. So sicher. Nicht "EF-freundlich" ... aber manchmal eine Notwendigkeit des wirklichen Lebens – BLSully

+1

Re: Es gibt Anwendungsfälle dafür. Sicher genug. Aber die Frage zu beantworten, die "Datentabelle mit Entity Framework zurückgeben" war, ist eine schlechte Antwort. Auch im Allgemeinen, es sei denn, Sie sind in einer Ausnahme wie Sie erwähnt, dies ist kein guter Code für Leute, von denen zu arbeiten. Siehe meine Antwort unten. –

6

Dieses Beispiel wird wieder ein datatable Objekt Auswählen von Daten aus EntityFramework.

Ich glaube, das ist die beste Lösung für das Ziel. Das Problem bei dieser Lösung besteht jedoch darin, dass jeder Datensatz aufgelistet wird. Vielleicht möchten Sie Filter die Liste zuerst dann führen Sie diese aus der Liste, um das zu vermeiden.

DataTable dt = new DataTable(); 
(from rec in database.Table.AsEnumerable() 
        select new 
        { 
         id = rec.id, 
         name = rec.Name 
         //etc 
        }).Aggregate(table, (dt, r) => 
        { 
         dt.Rows.Add(r.id, r.Name); 
         return dt; 
        }); 
+0

Dank John, ich suchte nach einem Weg, der tatsächlich Entity Framework verwendet. –

+0

Das ist in Ordnung, aber es beantwortet diese spezielle Frage überhaupt nicht. In Ihrer Antwort haben Sie 'datbase.Table'. Sie arbeiten in Ihrem Fall mit einer Entität, während sich die Frage auf eine Datentabelle bezieht, in der die Eigenschaften unbekannt sind. Mit einer DataTable können Sie den zurückgegebenen Datensatz einschließlich seiner Spaltenanzahl und -namen beobachten. Und natürlich die Daten. Wenn Sie E.F. und Entities, hauptsächlich LinqToSQL oder LinqToEntities, unter Tausenden von Codezeilen verwenden, aber EINEN Fall haben, wo Sie eine DataTable benötigen, um einen unbekannten Datensatz zu beobachten, funktioniert Ihre Antwort überhaupt nicht. – Suamere

1

einfach die bisherige Lösung zu verbessern, jetzt generische Parameter (nicht SQL Server-spezifisch) und mutiple Result Unterstützung:

DataSet GetDataSet(string sql, CommandType commandType, Dictionary<string, Object> parameters) 
    { 
     // creates resulting dataset 
     var result = new DataSet(); 

     // creates a data access context (DbContext descendant) 
     using (var context = new MyDbContext()) 
     { 
      // creates a Command 
      var cmd = context.Database.Connection.CreateCommand(); 
      cmd.CommandType = commandType; 
      cmd.CommandText = sql; 

      // adds all parameters 
      foreach (var pr in parameters) 
      { 
       var p = cmd.CreateParameter(); 
       p.ParameterName = pr.Key; 
       p.Value = pr.Value; 
       cmd.Parameters.Add(p); 
      } 

      try 
      { 
       // executes 
       context.Database.Connection.Open(); 
       var reader = cmd.ExecuteReader(); 

       // loop through all resultsets (considering that it's possible to have more than one) 
       do 
       { 
        // loads the DataTable (schema will be fetch automatically) 
        var tb = new DataTable(); 
        tb.Load(reader); 
        result.Tables.Add(tb); 

       } while (!reader.IsClosed); 
      } 
      finally 
      { 
       // closes the connection 
       context.Database.Connection.Close(); 
      } 
     } 

     // returns the DataSet 
     return result; 
    } 
+2

Sie kopieren und fügen diese Antwort in mehrere Fragen ein ([1] (http://stackoverflow.com/a/35608488/189134), [2] (http://stackoverflow.com/a/35608325/189134)) . Bitte hör auf. Die Antworten dienen nicht dazu, den gleichen Textblock immer wieder zu löschen. Konzentrieren Sie sich stattdessen auf die Frage und beantworten Sie, was gefragt wird. Ein langer Textblock macht das nicht. – Andy

2

Diese Lösung ist einfach, sehr schnell und einfach zu bedienen.

erstellen DbContext Erweiterung:

using System.Data; 
using System.Data.Common; 
using System.Data.Entity; 
.. 
.. 
public static class DbContextExtensions 
{ 
    public static DataTable DataTable(this DbContext context, string sqlQuery) 
    { 
     DbProviderFactory dbFactory = DbProviderFactories.GetFactory(context.Database.Connection); 

     using (var cmd = dbFactory.CreateCommand()) 
     { 
      cmd.Connection = context.Database.Connection; 
      cmd.CommandType = CommandType.Text; 
      cmd.CommandText = sqlQuery; 
      using (DbDataAdapter adapter = dbFactory.CreateDataAdapter()) 
      { 
       adapter.SelectCommand = cmd; 

       DataTable dt = new DataTable(); 
       adapter.Fill(dt); 

       return dt; 
      } 
     } 
    } 
} 

Beispiele:

using (MyDbContext db = new MyDbContext()) 
{ 
    string query = db.Students.Where(o => o.Age > 20).ToString(); 

    DataTable dataTable = db.DataTable(query); 

    .. 

    DataTable dt = db.DataTable(
         ( from o in db.Studets 
          where o.Age > 20 
          select o 
         ).ToString() 
        ); 
}