How to map property to first of many in Fluent NHibernate?
Given a parent child relationship between User
and FailedLogin
where a user has many failed logins. I'd like to map this into
class User
{
public virtual FailedLogin LastFailedLogin { get; set; }
}
class FailedLogin
{
public virtual User User { get; set; }
public virtual DateTime AttemptOn { get; set; }
}
So that the LastFailedLogin
property contains the FailedLogin
with the most recent AttemptOn
date and time. If LastFailedLogin
is set it should save that FailedLogin
to the database (i.e. .Cascade.SaveUpdate()
) Note, I do not want to map a collection of all FailedLogins for this user for performance reasons.
I have been totally unable to write a fluent mapping for this. How do I map this using Fluent NHibernate?
public class UserMap : ClassMap<User&g开发者_JS百科t;
{
public UserMap()
{
// What goes here for LastFailedLogin?
}
}
public class FailedLoginMap: ClassMap<FailedLogin>
{
public FailedLoginMap()
{
References(x => x.User).Not.Update();
Map(x => x.AttemptOn).Not.Update();
}
}
i cant see a direct solution but there would be with an internal list:
class User
{
internal virtual IList<FailedLogin> LastFailedLogins { get; set; }
public virtual FailedLogin LastFailedLogin { get { LastFailedLogins.FirstOrDefault(); } set { LastFailedLogins.Insert(0, value); } }
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
HasMany(u => u.LastFailedLogins)
.OrderBy("AttemptOn desc");
}
}
The solution I settled on, which I'm not entirely happy with, is:
public class User
{
private readonly IList failedLogins;
public virtual FailedLogin LastFailedLogin
{
get
{
return failedLogins.FirstOrDefault();
}
set
{
failedLogins.Clear();
failedLogins.Add(value);
}
}
}
public class UserMap : ClassMap<User>
{
HasMany(Reveal.Member<User, IEnumerable<FailedLogin>>("failedLogins"))
.Where("FailedLoginID=(SELECT TOP 1 a.FailedLoginID FROM FailedLogin AS a " +
"WHERE a.UserID = UserID ORDER BY a.AttemptOn DESC)")
.Cascade.SaveUpdate().Access.CamelCaseField().Inverse();
}
This solution ensures that only a single FailedLogin
is loaded with the User
. It also handles correctly saving a new failed login that is associated to the user. Finally it ensures that the implementation is hidden from consumers of the User
class. Unfortunately, this still imposes persistence concerns on the User
class.
精彩评论