Laden...

Dynamische LinQ to SQL Abfragen - dynamische Tabellen

Erstellt von D-eath vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.496 Views
D
D-eath Themenstarter:in
233 Beiträge seit 2008
vor 14 Jahren
Dynamische LinQ to SQL Abfragen - dynamische Tabellen

Silverlight 4 Beta
VS2010
LinQ to SQL auf SQL Server 2008

Hallo,

ich habe einen Tabellennamen und zwei Spaltennamen vorliegen. Diese können sich beliebig ändern.
Mein Ziel ist es, eine SQL Abfrage zu erstellen wie SELECT [spalte1], [spalte2] FROM table und die Ergebnisse dieser Abfrage dann in meiner Silverlight Anwendung an irgendein Control zu hängen.

Welche Möglichkeit habe ich hierzu?
Ich habe es mal mit einer eigenen Klasse versucht, die die Spalten aufnimmt, leider bekomme ich immer für alle Einträge null zurück.
GetTable als Generic läuft bei mir auch nicht, da ich folgende Meldung beim Einbinden der Servicereferenz bekomme:

System.Collections.Generic.List`1[TEntity]' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types.

Das war Versuch 1:

        [OperationContract]
        public List<TEntity> GetDataSource<TEntity>(string pvsQuery, params object[] pvoParams) where TEntity: class
        {
            System.Data.Linq.Table<TEntity> lvoTable = db.GetTable(typeof(TEntity)) as System.Data.Linq.Table<TEntity>;

            var selected_rows = from rows in lvoTable
                                select rows;

            return selected_rows.ToList();
        }

Versuch 2 war folgender:

        public List<ccDataSource> GetDataSource(string pvsQuery, params object[] pvoParams)
        {
            var lvoQuery = db.ExecuteQuery<ccDataSource>(pvsQuery, pvoParams);
            List<ccDataSource> lvoReturnList = new List<ccDataSource>();

            foreach (ccDataSource c in lvoQuery)
            {
                lvoReturnList.Add(new ccDataSource(c.DataValueField, c.DataTextField));
            }

            return lvoReturnList;
        }

Hier die Klassenimplementierung für ccDataSource:

 public class ccDataSource
    {
        private string lvsDataValueField;
        private string lvsDataTextField;

        public string DataValueField
        {
            get
            {
                return lvsDataValueField;
            }
            set
            {
                lvsDataValueField = value;
            }
        }

        public string DataTextField
        {
            get
            {
                return lvsDataTextField;
            }
            set
            {
                lvsDataTextField = value;
            }
        }

        public ccDataSource()
        {
            lvsDataValueField = string.Empty;
            lvsDataTextField = string.Empty;
        }

        public ccDataSource(string pvsDataValueField, string pvsDataTextField)
        {
            lvsDataValueField = pvsDataValueField;
            lvsDataTextField = pvsDataTextField;
        }
    }

Leider sind alle Felder hier schon beim Query null, allerdings bekomme ich die richtige Anzahl an Feldern zurück. Kann ich hier irgendwie einen Konstruktor erstellen, der mit select new arbeitet? Wenn ja, wie? Ich bin bis jetzt noch nicht dahinter gestiegen.

Versuch 3 war per Stored Procedure, aber da bekomme ich, da ich ja einen dynamischen SQL String zusammenbaue und per exec ausführen lasse, nur einen Integer-Wert zurück. Das bringt mich also nicht weiter.

Hat jemand noch eine Idee?

Grüße
T.

61 Beiträge seit 2009
vor 14 Jahren

Hallo D-eath,

ich arbeite regelmäßig mit LinQToSQL, aber leider habe ich nur halbwegs dynamische Lösungen gefunden.
Ich kann dir aber vielleicht ein paar gute Tipps geben, da mir einiges aufgefallen ist.

Zum Beispiel die Klasse, die als Entität verwendet wird.
Ich habe ein Beispiel erstellt, wie man es in der Regel bei LinQToSQL löst:


    [System.Data.Linq.Mapping.Table(Name = "tblPersonen")]
    public class Person
    {
        private int _ID;
        private string _vorname;
        private string _nachname;

        [System.Data.Linq.Mapping.Column(Name = "personID", Storage = "_ID", CanBeNull = false, IsPrimaryKey = true)]
        public int ID
        {
            get { return this._ID; }
        }

        [Column(Name = "vorname", Storage = "_vorname", CanBeNull = true)]
        public string Vorname
        {
            get { return this._vorname; }
            set { this._vorname = value; }
        }

        [Column(Name = "nachname", Storage = "_nachname", CanBeNull = true)]
        public string Nachname
        {
            get { return this._nachname; }
            set { this._nachname = value; }
        } 
    }

Wichtig sind die Attribute, da die GetTable<TEntity>()-Methode und die GetTable(System.Type entityType)-Methode nach genau diesen Attributen suchen und daraus sowohl die Abfrage für die Datenbank erstellen als auch die Werte auf die Felder (die privaten) über die Reflection zugreifen und die Werte zuweisen.

Wenn diese Attribute nicht gesetzt sind, dann weiß die Methode nicht wo sie diese zuordnen soll. Das ColumnAttribute benötigt i.d.R. nur den Storage-Wert, da es darüber via Reflection auf das "private" Feld zugreift und den Wert festlegt. Die anderen Werte sind optional.
Z.B. stellt der Wert "Name" den Namen der Spalte in der DatenbankTabelle dar. Ist dieser Name nicht angegeben, wird stattdessen der Name der Eigenschaft als Spaltenname genutzt.

Ich hoffe das kann dir oder jemand anders vorerst weiterhelfen.

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.