エンティティの1対多の関係を照会したいと思います。Nhibernate - Linqと1対多数の関係を照会
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
}
}
次流暢マッピング(マッピングは一種の無関係です、私は唯一の指導のためにここにこれを入れている)で
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() {
}
}
:さらに私の問題を説明するために、想像私のアプリケーションは、以下のエンティティを持っています
ご覧のとおり、ユーザーは多数のメンバーシップを持つことができます。 CurrentMembership(ユーザーに対するプロパティ)は、IsValidプロパティがtrueのユーザーに対してメンバシップを返します(これは、ユーザーに対する単一のメンバシップにのみ該当します)。
現在、現在のメンバーシップが20日以内に残っているすべてのユーザーを取得したいと考えています。
私の最初の試みが言っていた:
session.Linq<User>().Where(u => u.CurrentMembership.DaysLeft < 20).ToList();
しかし、これはエラー投げた:
"プロパティを解決できませんでした:のCurrentMembership:ユーザー"
をこれは一種のI以来、期待されましたこのプロパティのフォーミュラマッピングを使用しませんでした(メンバーシップに対するDaysLeftおよびIsValidプロパティの場合と同じように)。文字列、int、およびboolをマッピングする以外の数式マッピングを使用する方法がわかりません。次の私が言ってみました:
session.Linq<User>().Where(u => u.Membership.Single(m => m.IsValid).DaysLeft < 20).ToList();
しかし、これはエラー投げた:「オブジェクトのインスタンスに設定されていないオブジェクト参照」
を
私はこのメンバーシップを直接照会することができますが、私はこれを多くの場所で行う例として使っています。私はLinqでそれをクエリすることができますCurrentMembershipプロパティをマッピングする別の方法を提案することができます。最適なパフォーマンスが必要なので、リストに変換してメモリで作業するだけでは十分ではないことに注意してください。
私は助けていただきありがとうございます。ありがとう
新しいLinqプロバイダはごみです。多くの問題がありますが、最大の理由は、Skip/Takeの前にFetchを呼び出すことができないということです。これらが解決されるまで、私はアップグレードする立場にはいません。 – nfplee
あなたはQueryOver APIを試しましたか?これはNH 3.0用の私のデフォルトAPIです。 LINQと非常によく似ていますが、Criteria APIの大部分の機能(それを囲むラッパー)を備えています。残念なことに、古いLINQはデッドエンドです。そのような制限は固定されません。 – Meligy
QueryOverは有望そうですが、私はLinqの柔軟性が好きです。将来的に私のアプリケーションをエンティティフレームワークにアップグレードしたい場合は、これは簡単なことです。私は今は古いプロバイダに固執することに決めましたが、NHibernate 3またはEntity Frameworkにアップグレードする予定がある場合は、かなりの痛みはないように、私は単体テストを作成しています。 – nfplee