verwendetes Datenbanksystem: MSSQL
Moin!
Hier zunächst die wichtigsten Klassen aufs wesentliche reduziert:
public abstract class DataValue
{
[Column(IsPrimaryKey = true)]
public Guid Id { get; internal set; }
[Column(IsDiscriminator = true)]
private string Class;
[Column]
public Guid? MetadataId { get; internal set; }
private EntityRef<Bracket> _Metadata;
[DataMember]
[Association(ThisKey = "MetadataId", OtherKey = "Id")]
internal Bracket Metadata { get { return _Metadata.Entity; } set { _Metadata.Entity = value; } }
internal virtual IQueryable FindEqualInList([NotNull]IQueryable list)
{
return list.Cast<DataValue>().Where(dv => dv.MetadataId == MetadataId || dv.MetadataId == null && MetadataId == null);
}
}
public class BoolValue : SimpleValue
{
[Column(CanBeNull = true)]
private bool? boolValue;
internal override IQueryable FindEqualInList(IQueryable list)
{
return base.FindEqualInList(list.OfType<BoolValue>().Where(bv => bv.boolValue == null && boolValue == null || bv.boolValue == boolValue));
}
}
public class Bracket : DataValue
{
[Association(OtherKey = "SourceItemId")]
internal EntitySet<ValueAssign> _BracketValues = new EntitySet<ValueAssign>();
internal override IQueryable FindEqualInList(IQueryable list)
{
return base.FindEqualInList(list.OfType<Bracket>()).Cast<Bracket>().Where(sv => sv._BracketValues.Count() == _BracketValues.Count).ToList().FindAll(sv =>
sv._BracketValues.All(va1 => _BracketValues.FirstOrDefault(va2 =>
va2.Ordinal == va1.Ordinal && va2.DestinationItemId == va1.DestinationItemId) != null)).AsQueryable();
}
}
public class ValueAssign
{
[Column(IsPrimaryKey = true)]
internal Guid SourceItemId { get; set; }
[Column]
public Guid DestinationItemId { get; internal set; }
[Column(IsPrimaryKey = true)]
public int Ordinal { get; internal set; }
private EntityRef<DataValue> _DestinationItem;
[Association(ThisKey = "DestinationItemId", OtherKey = "Id")]
public DataValue DestinationItem
{
get { return _DestinationItem.Entity; }
set { _DestinationItem.Entity = value; }
}
}
Wenn ein neuer DataValue gespeichert werden soll, rufe ich für diesen zunächst FindEqualInList() mit der Tabelle als Parameter auf um zu sehen, ob es schon einen identischen Wert gibt... Das funktioniert auch wunderbar. Leider verlasse ich in dem FindEqualInList in der Klasse Bracket den DataBase-Context in dem Moment in dem ich das ToList() aufrufe. Hier werden alle in Frage kommenden Brackets aus der DB geladen und dann wird die Liste weiter eingeschränkt. Ich mache das ToList().FindAll(), da ein Where nicht funktioniert, da die weitere Lambda-Expression nicht in SQL übersetzt werden kann.
Nun meine Frage: (Wie) kann ich die Lambda-Expression so umwandeln, dass sie in SQL übersetzbar ist? Das würde das Laden in den Speicher verhindern und sicher wesentlich schneller laufen.
Vielen Dank schon mal in voraus.
T-Man
Hallo,
in dem du ExpressionTrees verwendest.
EIn beispiel:
Expression<Func<string, bool>> exp = (s) => s.Length > 1;
mfg
serial
Danke für den Tipp, er führt mich schon etwas weiter. Leider noch nicht zum Ziel.
ExpressionTrees verstehe ich jetzt ungefähr. Für einfachere Abfragen könnte ich auch einen aufstellen.
Hier müsste ich ja sowas wie
Where(sv => sv._BracketValues[0].DestinationItemId == _BracketValues[0].DestinationItemId &&
sv._BracketValues[1].DestinationItemId == _BracketValues[1].DestinationItemId && ...)
dynamisch erstellen.
Aber wie referenziere ich die einzelnen Elemente von _BracketValues um sie zu vergleichen? Der Indexer und ElementAt sind nicht in SQL übersetzbar, sprich, mein Beispiel funktioniert nicht.
Kann mir da jemand einen weiteren Tipp geben?
Danke!
T-Man
OT:
@T-Man: wo hast Du das NotNullAttribute her? Habe ich was verpaßt oder ist das eine Eigenkreation?
OT:
@T-Man: wo hast Du das NotNullAttribute her? Habe ich was verpaßt oder ist das eine Eigenkreation? Von ReSharper. Das hätte ich hier weglassen können...
Ich weiß jetzt wie es theoretisch geht.
Da ich nur herausfinden sollte, ob es geht kann ich hier nicht die konkrete Lösung präsentieren.
Gruß
T-Man
Eine kleine Expression-Bastelei findest du z.B. unter [ExtensionMethods] LeftOuterJoin für IQueryable (und IEnumerable)