rivantsov / vita

VITA Application Framework
MIT License
59 stars 15 forks source link

Set value in MN entity #142

Closed jasonlaw closed 4 years ago

jasonlaw commented 4 years ago

Hi,

Suppose I have following MN entity models:

public interface IUserInCommunity
{
  IUser User { get; set; }
  ICommunity Community { get; set; }
  bool IsAdmin { get; set; } // How to set this to true before save?
}

public interface ICommunity
{
  [ManyToMany(typeof(IUserInCommunity))]  
  List<IUser> Users  { get; set; }
}

public interface IUser
{
  [ManyToMany(typeof(ICommunity))]  
  List<ICommunity> Communities  { get; set; }
}

In order to set the IsAdmin value to true, I have to first SaveChanges to create the entity, then select back the entity and set the value, and finally SaveChanges again.

Is there a way to define the value in MN entity before it is created?

Thanks in advance.

rivantsov commented 4 years ago

you can hook to entity event, called New. For books app, something like this, after app is initialized:

        var bookEntInfo = BooksApp.Model.GetEntityInfo(typeof(IBook));
        bookEntInfo.Events.New += OnNewBook;

and in event handler

    private static void OnNewBook(Entities.Runtime.EntityRecord record, EventArgs args) {
      var book = (IBook)record.EntityInstance;
      book.SpecialCode = "some code"; //init whatever you want
    }
jasonlaw commented 4 years ago

Clear now, thanks!

jasonlaw commented 4 years ago

I found that in the MN "New" event, the parent object is null. In my case, I need the access to its parent object, as following code:

 public static void OnNewMemberInCommunity(IMemberInCommunity mic)
        {            
            if ( mic.Community.Members.Count == 1)
            {
                // Set as admin if he/she is the only member in the community
                mic.Admin = 2;
            }
        }

Could you please advise how to achieve this?

Thanks!

rivantsov commented 4 years ago

oh man, at this point, the entity (mic) is just created, it is not initialized yet, nothing is assigned. you probably should instead use ValidatingChanges event - it is called before SaveChanges (actually inside it, before sending to database). You can check record.Status prop (if rec.Status == EntityStatus.New) to filter new records only But - be aware, you touch Members list, so it will cause immediate load of members if they are not loaded. That might have perf impact, or maybe some side effects, double-test it

rivantsov commented 4 years ago

and it looks like, my guess, is that Admin should better be assigned explicitly in the code that creates this first member in community, EXPLICITLY. Things like this should not be hidden somewhere inside automatic events, better do the directly in the creation logic. Just from the point of view of code clarity and maintainability. And better simply change from many-to-many to many-to-one, with this extra prop Admin exposed explicitly

jasonlaw commented 4 years ago

I really like the simplicity of the automation of MN objects, but I think you got the point, I will change the design to many-to-one instead. Thanks again for your valuable advice, really appreciate it.