Ich möchte eine Eins-zu-viele-Beziehung auf einer Entität abfragen. Um zu helfen, mein Problem weiter zu erläutern, stellen Sie sich meine Anwendung die folgenden Einheiten hat:Nhibernate - Query Eins-zu-viele-Beziehung mit Linq
public class User {
public virtual int UserID { get; set; }
public virtual Membership CurrentMembership {
get { return Membership.Single(m => m.IsValid); }
}
public virtual IList<Membership> Membership { get; private set; }
public User() {
Membership = new List<Membership>();
}
}
public class Membership {
public virtual int MembershipID { get; set; }
public virtual User User { get; set; }
public virtual DateTime StartDate { get; set; }
public virtual DateTime? EndDate { get; set; }
public virtual int DaysLeft { get; set; }
public virtual bool IsValid { get; set; }
public Membership() {
}
}
Mit dem folgende Fluent Mapping (die Abbildung ist eine Art irrelevant, ich habe das hier nur zur Orientierung) setzen:
public class UserMap : ClassMap<User> {
public UserMap() {
Table("Users");
Id(x => x.UserID);
HasMany(x => x.Membership)
.KeyColumn("UserID")
.Inverse()
.Cascade.All();
}
}
public class MembershipMap : ClassMap<Membership> {
public MembershipMap() {
Table("Membership");
Id(x => x.MembershipID);
References(x => x.User);
Map(x => x.StartDate);
Map(x => x.DaysLeft)
.Formula("CASE WHEN EndDate IS NOT NULL AND dbo.DayDiff(GETUTCDATE(), EndDate) > 0 THEN dbo.DayDiff(GETUTCDATE(), EndDate) ELSE 0 END");
// DayDiff is a udf which gets the number of days between two dates
Map(x => x.IsValid)
.Formula("CASE WHEN dbo.GetValidMembershipID(UserID) = MembershipID THEN 1 ELSE 0 END");
// GetValidMembershipID is a udf which works out the valid membership id for this user
}
}
Wie Sie sehen können, kann ein Benutzer viele Mitgliedschaften haben. Die CurrentMembership (Eigenschaft für den Benutzer) gibt die Mitgliedschaft für den Benutzer zurück, bei der die IsValid-Eigenschaft wahr ist (dies gilt nur für eine einzelne Mitgliedschaft für den Benutzer).
Jetzt möchte ich in der Lage sein, alle Benutzer zu greifen, deren aktuelle Mitgliedschaft weniger als 20 Tage hat.
Mein erster Versuch war zu sagen:
session.Linq<User>().Where(u => u.CurrentMembership.DaysLeft < 20).ToList();
Aber das warf den Fehler:
"nicht Eigentum lösen könnte: CurrentMembership von: User"
Dies war irgendwie da ich erwartet habe keine Formelzuordnung für diese Eigenschaft verwendet (wie ich es für die DaysLeft- und IsValid-Eigenschaften für die Mitgliedschaft getan habe). Ich kann nicht sehen, wie Sie Formel Mapping anders als zum Zuordnen von Strings, Ints und Bools verwenden können. Weiter habe ich versucht zu sagen:
session.Linq<User>().Where(u => u.Membership.Single(m => m.IsValid).DaysLeft < 20).ToList();
Aber das warf den Fehler: „Der Objektverweis wurde nicht auf eine Instanz eines Objekts festgelegt“
Ich weiß, ich könnte diese Mitgliedschaft direkt abfragen, aber ich habe dies als ein Beispiel für etwas, was ich in vielen Orten. Könnte jemand eine alternative Möglichkeit vorschlagen, die CurrentMembership-Eigenschaft zuzuordnen, die es mir ermöglicht, sie mit Linq abzufragen. Bitte beachten Sie, dass ich eine optimale Leistung benötige. Die Konvertierung in eine Liste und die Arbeit im Speicher reichen nicht aus.
Ich würde die Hilfe zu schätzen wissen. Danke
Der neue Linq-Anbieter ist Quatsch. Es gibt viele Probleme, die größte ist, dass ich Fetch vor einem Skip/Take nicht aufrufen kann. Bis diese behoben sind, kann ich nicht upgraden. – nfplee
Haben Sie die QueryOver API ausprobiert? Es ist meine Standard-API für NH 3.0. Sehr ähnlich wie LINQ, aber mit den meisten Merkmalen der Kriterien-APIs (es ist ein Wrapper dafür). Die alte LINQ ist leider eine Sackgasse. Irgendwelche Begrenzungen oder so werden einfach nicht behoben. – Meligy
QueryOver sieht vielversprechend aus, aber ich mag die Flexibilität, die ich mit Linq bekomme. Wenn ich in Zukunft jemals meine Anwendung auf das Entity-Framework aufrüsten möchte, sollte das trivial sein. Ich habe beschlossen, bei dem alten Anbieter zu bleiben, aber ich bin gerade dabei, ein paar Komponententests zu schreiben, so dass es ziemlich schmerzlos sein sollte, wenn ich ein Upgrade auf NHibernate 3 oder das Entity Framework plane. – nfplee