So I have for example these models:
public class Account
{
public Guid ID {get;set;}
[ForeignKey("Profile")]
public Guid? ProfileId {get;set;}
public virtual Profile Profile {get;set;}
......
}
public class Profile
{
public Guid ID {get;set;}
[ForeignKey("Account")]
public Guid AccountId {get;set;}
public virtual Account Account {get;set;}
}
Then I have a view (html) which request from a controller.
public class ExController : ApiController
{
public async Task<Account> GetAccount(Guid id)
{
return await db.Accounts.Where(m => m.ID == id).FirstOrDefaultAsync();
}
}
Then the html view edit / update the account entity, then pass it again to controller to be saved into database. If I just save from the raw passed entity from the view, the Profile
will be treated as new entity. This is not what I want, I want the Account
and Account.Profile
to be updated, not added.
For example:
public async Task UpdateModel(Account model)
{
db.Accounts.Attach(model);
db.Entry(model).State = EntityState.Modified;
await db.SaveChangesAsync();
}
The child profile inside model
will be treated as new entity.
How can I update the children entities as well?
EDIT
So my purpose is not using entity as view model
. I am developing an object mapper which map all properties from vm to model and vise versa.
Something like this:
vm.MapTo<Model>(ref existing);
The problem is EF always sees the children entity mapped from view model
as new entities.
EDIT
This is my mapping function
public void MapTo<T>(ref T instance)
{
var fromProperties = this.GetType().GetProperties();
var toProperties = typeof(T).GetProperties();
foreach (PropertyInfo prop in fromProperties)
{
string propName = prop.Name;
if (prop.CustomAttributes.Count() > 0)
{
MapToAttribute mapAttribute = (MapToAttribute)Attribute.GetCustomAttribute(prop, typeof(MapToAttribute));
AutoGeneratedAttribute autoGeneratedAttribute = (AutoGeneratedAttribute)Attribute.GetCustomAttribute(prop, typeof(AutoGeneratedAttribute));
if (mapAttribute != null)
propName = mapAttribute.MappedProperty;
if (autoGeneratedAttribute != null)
propName = "";
}
PropertyInfo mappedProp = toProperties.Where(m => m.Name == propName).FirstOrDefault();
if (mappedProp != null)
{
object value = prop.GetValue(this);
if (value != null && value.GetType() == typeof(DateTime))
{
DateTime dateValue = ((DateTime)(value)).ToUniversalTime();
mappedProp.SetValue(instance, dateValue);
}
else if (value != null && value.GetType() == typeof(DateTime?))
{
DateTime? dateValue = ((DateTime?)(value)).Value.ToUniversalTime();
mappedProp.SetValue(instance, dateValue);
}
else
{
mappedProp.SetValue(instance, value);
}
}
}
}