Search code examples
c#nhibernatefluent-nhibernatenancy

Fluent hHibernate One-To-Many set value in blank


first of all, sorry for my bad English

I have the following entities

public  class User
{
    public virtual int Id { get; set; }

    public virtual Application Application { get; set; }


    public User ()
    {
     Application = new Application ();
    }

}

UserMap

 public class UserMap : ClassMap<User>
{
    public UserMap ()
    {
        Table ("Users");
        Id (p => p.Id);
        References (x => x.Application).Cascade.SaveUpdate ();


    }
}

Application

public class Application
{
    public virtual int Id { get; set; }

    public virtual string ApplicationName { get; set; }

}

ApplicationMap

 public ApplicationMap ()
    {
        Table ("Applications");
        Id (x => x.Id);
        Map (x => x.ApplicationName);

    }

I received this json

{

"Application": 1,

}

and save the object this way

                    var user = new User();

                    user.Application.Id = Cast.To<int>(userModel.Application);

                    userService.Add(user);
                    userService.Commit();

Correctly records the data in the table "users" but left blank, the "ApplicationName" table field "application"

I think the error is in this line (user.Application.Id = Cast.To (userModel.Application);) because I did not set  "ApplicationName" field   but if I get the id as a parameter, I will need to get the application object by id, and assign the user object?. thank you very much


Solution

  • You are right, conversion from ID into Entity (Applicaton) will require call to data layer and its operation GetById().

    session.Load<Application>(id)

    In cases, that we can be sure, that the passed Application ID exists, NHibernate has a dedicated way how to convert ID into its ENTITY. It is a Load() method, which does NOT hit the DB, just creates a proxy with provided ID, and the operation will succeed:

    var user = new User();
    
    var applicationId = Cast.To<int>(userModel.Application);
    
    //                behind is session.Load<Aplication>(applicaitonId)
    var application = applicationService.Load(applicationId);
    
    user.Application = application;
    userService.Add(user);
    

    session.Get<Application>(id)

    The alternative is a Get() method, which always loads the instance by ID, i.e. hits the DB. If the ID does not match any ID, null is returned. Advantage in this scenario is, that we can even change the referenced ApplicaitonName (if application exists)

    var user = new User();
    
    var applicationId = Cast.To<int>(userModel.Application);
    
    //                behind is session.Get<Aplication>(applicaitonId)
    var application = applicationService.GetById(applicationId);
    
    if(application !== null)
    {
        application.ApplicationName = ... // here we can even change that;
        user.Application = application;
    }
    

    cascade for new.

    In case we would recieve brand new object

    {
      "Application": { "ApplicaitonName" : ... }
    }
    

    We can create one, and because of Cascading setting above, it will work as well

    user.Application = new Appliation 
    { 
      ApplicationName = ...,
    }