2016-09-04 1 views
0

Haftungsausschluss: erster C# -Projektein mehrdimensionales Objekt assoziativ Rückkehr von linq2entities

ich auf einem Export Skript gerade arbeitete, die CSV-Daten aus einer SQL-Datenbank muss exportieren. Ich versuche, linq2entities dazu zu bringen, die meiste Arbeit zu tun, um unnötige Schleifen zu vermeiden.

Ich möchte jedoch meine linq2sql Antwort in zwei Objekte (oder ein Unterobjekt, siehe unten als "calcs") trennen, von denen der Unterinhalt in der Lage sein muss, mir ein Schlüssel/Wert-Paar zu liefern, wie ich will Ich benötige später den Schlüsselnamen in meinen Berechnungen, um die Ausgabe einem zugeordneten Schlüssel aus einer anderen Tabelle zuzuweisen.

Ich habe ein paar Iterationen versucht, kann aber nicht für die unten arbeiten. Die Syntax scheint korrekt zu sein, aber wie es jetzt ist (unten) kann ich nicht einmal eine Zählung bekommen (Any), wenn ich sie einfach als normale Liste erstelle, bekomme ich eine Zeilenzahl, aber ich kann nicht auf das Unterobjekt innerhalb der 2. foreach Schleife zugreifen .

Also ist es möglich, ein gemischtes "Unterobjekt" von linq2sql zurück zu geben, und wenn nicht, was ist meine Optionen?

public ActionResult Process() 
    { 
     // Getting the data: 
     using (printmanEntities db = new printmanEntities()) 
     { 

      var result = (
       from u in db.CustomerUsages 
       join c in db.Customers on u.CustomerId equals c.Id 
       join e in db.Centers on u.CenterId equals e.id 
       where u.Status == 1 
       group u by c.Code into gr 
       select new 
       { 
        CustomerId = gr.Key, 
        CenterCode = gr.FirstOrDefault().Center.CenterCode, 
        CustomerCode = gr.FirstOrDefault().Customer.Code, 
        // Is the below possible? 
        calcs = new List<KeyValuePair<string, int>> 
        { 
         new KeyValuePair<string,int>("TPrintBw",gr.Sum(u => u.TPrintBw)) , 
         new KeyValuePair<string, int>("TPrintCol", gr.Sum(u => u.TPrintCol)), 
         new KeyValuePair<string, int>("TCopyBw", gr.Sum(u => u.TCopyBw)), 
         new KeyValuePair<string, int>("TCopyCol", gr.Sum(u => u.TCopyCol)), 
         new KeyValuePair<string, int>("TScan", gr.Sum(u => u.TScan)), 
         new KeyValuePair<string, int>("TFaxBw", gr.Sum(u => u.TFaxBw)) 
        } 
       }); 

      if (result.Any()) 
      { 

       AllCodes = db.Codes.ToList(); 

       dt.Columns.Add("Date", typeof(DateTime)); 
       dt.Columns.Add("CenterCode", typeof(String)); 
       dt.Columns.Add("BLANK", typeof(String)); 
       dt.Columns.Add("CustomerCode", typeof(string)); 
       dt.Columns.Add("ServiceCode", typeof(string)); 
       dt.Columns.Add("Qty", typeof(Int32)); 

       foreach (var v in result) 
       { 
        // I need to iterate through the items in the subobject here: 
        foreach (var i in v.calcs) 
        { 
         if (i.Value > 0) 
         { 
          DataRow dr = dt.NewRow(); 
          dr["Date"] = DateTime.Now; 
          dr["CenterCode"] = v.CenterCode; 
          dr["BLANK"] = ""; 
          dr["CustomerCode"] = v.CustomerCode; 
          dr["ServiceCode"] = GetServiceCode(i.Key); 
          dr["Qty"] = i.Value; 
          dt.Rows.Add(dr); 
         } 

        } 
       } 

       StringBuilder sb = new StringBuilder(); 

       IEnumerable<string> columnNames = dt.Columns.Cast<DataColumn>(). 
                Select(column => column.ColumnName); 
       sb.AppendLine(string.Join(",", columnNames)); 

       foreach (DataRow row in dt.Rows) 
       { 
        IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString()); 
        sb.AppendLine(string.Join(",", fields)); 
       } 
       string filename = DateTime.Now.ToString("yyyyddMM") + ".csv"; 
       System.IO.File.WriteAllText(HttpContext.Server.MapPath(@"/csv/exports/" + filename), sb.ToString()); 

      } 
     } 

     return View(); 
    } 

Antwort

0

Das Problem mit Ihrer Anfrage ist, dass LINQ to Entities erfordert die Typen mit parameterlos Konstrukteuren und Eigentum Setter und KeyValuePair (sowie Tuple) Projizieren erfüllt nicht die Kriterien und nicht verwendet werden kann.

Eine Möglichkeit wäre, zu erstellen und Projekt auf Ihre eigene Art, ähnlich wie KeyValuePair aber kompatibel mit EF:

public class KeyValuePairDto<TKey, TValue> 
{ 
    public TKey Key { get; set; } 
    public TValue Value { get; set; } 
} 

und dann:

calcs = new List<KeyValuePairDto<string, int>> 
{ 
    new KeyValuePairDto<string, int> { Key = "TPrintBw", Value = gr.Sum(u => u.TPrintBw) }, 
    new KeyValuePairDto<string, int> { Key = "TPrintCol", Value = gr.Sum(u => u.TPrintCol) }, 
    new KeyValuePairDto<string, int> { Key = "TCopyBw", Value = gr.Sum(u => u.TCopyBw) }, 
    new KeyValuePairDto<string, int> { Key = "TCopyCol", Value = gr.Sum(u => u.TCopyCol) }, 
    new KeyValuePairDto<string, int> { Key = "TScan", Value = gr.Sum(u => u.TScan) }, 
    new KeyValuePairDto<string, int> { Key = "TFaxBw", Value = gr.Sum(u => u.TFaxBw) }, 
} 

Ein anderer Weg ist, um die Liste zu projizieren von anonymer Typ (über Array-Initialisierer kombiniert mit ToList), der unterstützt wird:

calcs = new [] 
{ 
    new { Key = "TPrintBw", Value = gr.Sum(u => u.TPrintBw) }, 
    new { Key = "TPrintCol", Value = gr.Sum(u => u.TPrintCol) }, 
    new { Key = "TCopyBw", Value = gr.Sum(u => u.TCopyBw) }, 
    new { Key = "TCopyCol", Value = gr.Sum(u => u.TCopyCol) }, 
    new { Key = "TScan", Value = gr.Sum(u => u.TScan) }, 
    new { Key = "TFaxBw", Value = gr.Sum(u => u.TFaxBw) }, 
}.ToList() 
+0

Ich habe meinen Code entsprechend Ihrem Programm aktualisiert (http://pastebin.com/ESMrywyQ), habe aber eine Ausnahme für ToList() erhalten - eine Ausnahme vom Typ 'System.Reflection.TargetInvocationException' ist in EntityFramework.SqlServer.dll aufgetreten, war aber im Benutzercode nicht behandelt Weitere Informationen: Vom Ziel eines Aufrufs wurde eine Ausnahme ausgelöst. Auch in meiner 2. foreach Schleife kann ich i.Value oder i.Key nicht lesen. – mauzilla

+0

(1) Welche EF Version benutzen Sie? Das obige funktioniert in EF6.1.3 (2) 'var i in v.calcs' Der Typ 'i' der Variablen ist der anonyme Typ mit den Eigenschaften 'Schlüssel' und 'Wert', also sollte der Code ohne Probleme kompiliert werden. –

+0

Verwenden von 6.1.3 - Es scheint etwas mit der Rückkehr zu sein, kann ich keine Werte aus der Abfrage abrufen. Ich fange an zu fühlen 2 Abfragen könnte die beste Option sein – mauzilla