在存储库模式的纯POCO实体更新问题 [英] Pure POCO entity update problem in repository pattern
问题描述
我在UserRepository一个问题,我想更新的用户。我不希望某些字段更新,如密码,除非另有说明。例如,当我从视图中传递用户,该服务存储库,它发出了一个空或空密码字符串的用户。此空被写入数据库(我不想)。
I have a problem in my UserRepository in which I want to update a user. I dont want certain fields updated, such as password, unless specified. For example, When I pass the User from the view, to the service to the repository, it sends up the user with a null or empty password string. This null gets written to the database (which I dont want).
如何处理的情况也是这样吗?
How do I handle a situation like this?
域
public class User
{
public int UserId { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
库
public User Save(User user)
{
if (user.UserId > 0)
{
User dbUser = context.Users.FirstOrDefault(u => u.UserId == user.UserId);
//What do I do here?
}
context.Users.AddObject(user);
context.SaveChanges();
return user;
}
比方说,在这种情况下,我的看法让我改变仅电子邮件
,所以被送回保存的唯一的事()
方法是: user.UserId
和 user.Email
,而 user.password的
为空。在我的情况下,数据库将引发错误,因为密码应为空。
Lets say in this case, my view allows me to change only Email
, so the only thing that gets sent back to the Save()
method are: user.UserId
and user.Email
while user.Password
is null. In my case, the database throws error because Password should be nullable.
推荐答案
独立POCO方案(你会不会从数据库更新之前加载用户):
您可以选择性地说哪些属性必须进行更新:
You can selectively say which properties must be updated:
public User Save(User user)
{
if (user.UserId == 0)
{
context.Users.AddObject(user);
}
else
{
context.Users.Attach(user);
ObjectStateEntry entry = context.ObjectStateManager.GetObjectStateEntry(user);
entry.SetModifiedProperty("Email");
}
context.SaveChanges();
return user;
}
您还可以创建你两个重载保存
方法。首先将更新整个对象,第二个将只更新明确选择属性:
You can also create two overloads of you Save
method. First will update whole object, second will update only explicitly selected properties:
public User Save(User user)
{
if (user.UserId == 0)
{
context.Users.AddObject(user);
}
else
{
context.Users.Attach(user);
context.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
}
context.SaveChanges();
return user;
}
public User Save(User user, IEnumerable<Expression<Func<User, object>>> properties)
{
if (user.UserId == 0)
{
context.Users.AddObject(user);
}
else
{
context.Users.Attach(user);
ObjectStateEntry entry = context.ObjectStateManager.GetObjectStateEntry(user);
foreach(var selector in properties)
{
string propertyName = PropertyToString(selector.Body);
entry.SetModifiedProperty(propertyName);
}
}
context.SaveChanges();
return user;
}
// Doesn't work for navigation properties!
private static string PropertyToString(Expression selector)
{
if (selector.NodeType == ExpressionType.MemberAccess)
{
return ((selector as MemberExpression).Member as PropertyInfo).Name;
}
throw new InvalidOperationException();
}
您将调用第二个重载是这样的:
You will call the second overload this way:
userRepository.Save(user, new List<Expression<Func<User, object>>>
{
u => u.Email
});
连接方案(你会从数据库更新之前加载用户):
您可以修改您的保存方法,接受委托,这样就可以控制更新将如何进行:
You can modify your Save method to accept delegate so that you can control how update will be performed:
public User Save(User user, Action<User, User> updateStrategy)
{
if (user.UserId > 0)
{
User dbUser = context.Users.FirstOrDefault(u => u.UserId == user.UserId);
updateStrategy(dbUser, user);
}
else
{
// New object - all properties should be saved
context.Users.AddObject(user);
}
context.SaveChanges();
return user;
}
您会调用该方法是这样的:
You will call the method this way:
var user = GetUpdatedUserFromSomewhere();
repository.Save(user, (dbUser, mergedUser) =>
{
dbUser.Email = mergedUser.Email;
});
总之,尽管我的例子你一定要想想达林的职位和特殊ModelViews进行更新。
Anyway, despite of my examples you should definitely think about Darin's post and special ModelViews for updating.
这篇关于在存储库模式的纯POCO实体更新问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!