Hi Pete!
I'm using Mobile Objects in my architecture. This means that DAL enties are
used by NHibernate and on server side. Then I convert those DAL entities to
Mobile Data Objects (DTO) and send them to client.
I've managed to overcome problem by introducting another DAL Entity:
public class UserWithRoleEntity : UserEntity
{
public virtual IList<RoleEntity> Roles { get; set; }
}
public class UserEntity : PersistentObject
{
public virtual string UserName { get; set; }
public virtual string Email { get; set; }
public virtual string Password { get; set; }
public virtual bool IsActive { get; set; }
public virtual bool IsActivated { get; set; }
public virtual DateTime RegistrationDate { get; set; }
}
and adding another mapping hbm file for UserWithRoleEntity:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true"
assembly="OnAgile.DAL" namespace="OnAgile.DAL.DataEntities">
<class name="UserWithRoleEntity" table="users" lazy="false"
polymorphism="explicit">
<id name="ID" column="id">
<generator class="native" />
</id>
<property name="UserName" column="user_name" not-null="true"/>
<property name="Password" column="password" not-null="true"/>
<property name="Email" column="email" not-null="true"/>
<property name="IsActive" column="is_active" type="boolean"
not-null="true"/>
<property name="IsActivated" column="is_activated" type="boolean"
not-null="true"/>
<property name="RegistrationDate" column="registration_date"
not-null="true"/>
<bag name="Roles" table="users_roles" lazy="true" cascade="all">
<key column="user_id"/>
<many-to-many column="role_id"
class="OnAgile.DAL.DataEntities.RoleEntity, NHibernateManyToMany"/>
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true"
assembly="OnAgile.DAL" namespace="OnAgile.DAL.DataEntities">
<class name="UserEntity" table="users" lazy="false">
<id name="ID" column="id">
<generator class="native" />
</id>
<property name="UserName" column="user_name" not-null="true"/>
<property name="Password" column="password" not-null="true"/>
<property name="Email" column="email" not-null="true"/>
<property name="IsActive" column="is_active" type="boolean"
not-null="true"/>
<property name="IsActivated" column="is_activated" type="boolean"
not-null="true"/>
<property name="RegistrationDate" column="registration_date"
not-null="true"/>
</class>
</hibernate-mapping>
This way I can easily create two methods in my DAL:
public User GetUser(int userID)
{
log.Trace(String.Format("GetUser({0})", userID));
User result = null;
using (var session = GetSession())
{
using (var tx = session.BeginTransaction())
{
try
{
var dataEntity = session.Load<UserEntity>(userID);
result = new
EntityConverter().FromDataEntity(dataEntity);
tx.Commit();
}
catch (Exception ex)
{
tx.Rollback();
log.ErrorException("Error while loading user", ex);
}
}
}
return result;
}
public User GetUserWithRoles(int userID)
{
log.Trace(String.Format("GetUserWithRole({0})", userID));
User result = null;
using (var session = GetSession())
{
using (var tx = session.BeginTransaction())
{
try
{
var dataEntity =
session.Load<UserWithRoleEntity>(userID);
result = new
EntityConverter().FromDataEntity(dataEntity);
tx.Commit();
}
catch (Exception ex)
{
tx.Rollback();
log.ErrorException("Error while loading user", ex);
}
}
}
return result;
}
The same story for saving enties (but more sophisticated). You can look
through my DAL
here<http://code.google.com/p/onagile/source/browse/trunk/OnAgile.Services/OnAgile.DAL/DataProvider.cs>:
if you're interested: Anyways thaks for response!
2011/10/20 Pete Appleton <[email protected]>:
> What does the server do with the updated User entity returned from the
> client? My immediate thought is that you're not really passing a User
> entity from the client to the server, but happen to be using the same
> class as a convenient "property horse"; so, the pattern I'd be inclined
> to consider would consist of something like this (on the server), with
> appropriate error & concurrency checking
>
> public ResultType UpdateDetails(User someUpdatedThings) {
> User userEntity = mySession.Get<User>(someUpdatedThings.ID);
> // need to check concurrency - does the user still exist, what
> if someone's changed it?
> userEntity.UserName = someUpdatedThings.UserName;
> // etc ...
> mySession.Commit(); // note, we never went near the Roles
> collection
>
> return new SuccessResult();
> }
>
> Of course, using the User entity in this way is really an abuse of the
> domain model because there's a bunch of stuff on the user that has no
> relevance to this function!
>
> I'm slightly curious that you mentioned using a many/many association
> between User and Role, but the C# is written with a single collection
> from User to Role (no Role.Users collection). Another thought is that
> you could consider wiring User.Roles as the inverse end and changing
> associations by changing the Role.Users collection; that way, my
> understanding is that NHibernate would be unaffected by changes to the
> User
>
> hope that's of some help...
>
>
> -----Original Message-----
> From: [email protected] [mailto:[email protected]] On
> Behalf Of Ilia Ternovich
> Sent: 20 October 2011 14:35
> To: nhusers
> Subject: [nhusers] Fine grained control over association
>
> Hi!
>
> I've got following domain model: Users -> Roles ( e.g. there are
> multiple users and multiple roles. Each user can have multiple roles).
>
> public class User
> {
> public int ID { get; set; }
> public string UserName { get; set; }
> public string Email { get; set; }
> public string Password { get; set; }
> public bool IsActive { get; set; }
> public bool IsActivated { get; set; }
> public DateTime RegistrationDate { get; set; }
> public IList<Role> Roles { get; set; }
>
> public User()
> {
> Roles = new List<Role>();
> }
>
> public override string ToString()
> {
> return String.Format("{0},{1},{2},{3}", ID, UserName,
> Password, IsActive);
> }
> }
>
> public class Role
> {
> public int ID { get; set; }
> public string Name { get; set; }
> public string Description { get; set; }
> public IList<Permission> Permissions { get; set; }
>
> public Role()
> {
> Permissions = new List<Permission>();
> }
>
> public override string ToString()
> {
> return String.Format("ID={0},Name={1}", ID, Name);
> }
> }
>
>
> I use standart many-to-many association using association table. It
> works perfectly, but I need more fine grained control over
> associations. There are some scenarios when I don't want to take
> associations between User->Role into account and simply ignore them
> (e.g. update only User (name, email etc)). Is it possible to ignore
> cascade=all option in mapping file in some scenarios, and not to
> ignore in others?
>
> To illustrate the idea here are two scenarios:
> 1. Work with user entities (general scenario) - change e-mail,
> password, userName etc. Server sends lightweight User entities to
> client with Roles collection empty (since we're not working with
> roles). Client updates User entities on UI and sends them back to
> server. Since Permissions collection is empty (and I don't want to
> transfer it from server to client and vise versa) NHibernate will
> remove associations between users and roles due to cascade=all
> 2. Work with user permissions (e.g. admin scenario). Server sends full
> User entities to client with Roles collection loaded. This way
> cascade=all does it job perfectly.
>
> So I need to tell NHbiernate somehow to ignore cascade=all in some
> cases and use this option in others. Is there any possibility to
> achieve this? Thanks!
>
> --
> You received this message because you are subscribed to the Google
> Groups "nhusers" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/nhusers?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups
"nhusers" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
[email protected].
> For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en.
>
>
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en.