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.

Reply via email to