有大量关于此的信息,但即使在阅读了几个小时和几个小时后,我似乎无法按照我想要的方式工作。
我正在尝试通过传入User对象并通常将更改与我从数据库中拉出的User对象进行比较来更新User对象。使用此方法时,我总是得到NotSupportedException:
已尝试附加或 或许,添加一个非新的实体 从另一个装载 DataContext的。这不受支持。
以下是我尝试这样做的方法:
public void SaveUser(User User)
{
using (DataContext dataContext = new DataContext(WebConfigurationManager.ConnectionStrings["database"].ConnectionString))
{
// New user
if (User.UserID == 0)
{
dataContext.Users.InsertOnSubmit(User);
}
// Existing user
else
{
User dbUser = dataContext.Users.Single(u => u.UserID.Equals(User.UserID));
Type t = dbUser.GetType();
foreach (PropertyInfo p in t.GetProperties())
{
if (p.CanWrite & p.GetValue(dbUser, null) != p.GetValue(User, null))
{
p.SetValue(dbUser, p.GetValue(User, null), null);
}
}
//dataContext.Refresh(RefreshMode.KeepCurrentValues, dbUser);
}
dataContext.SubmitChanges();
}
}
我评论过的评论栏也没有注释,但没有任何帮助。
如果我注释掉foreach()循环并添加一行像dbUser.UserName =“Cheese”;它会更新数据库中的用户名。这让我相信它与foreach()循环如何更改导致此失败的dbUser对象有关。
当我调试dbUser对象时,它似乎正确地获取了作为参数传递的User对象的所有更改。
我还对乐观并发做了一些阅读,并在数据类型时间戳表中添加了一列,但这似乎也没有任何效果。
我到底错在了什么?
如何通过一般性地检测已更改的内容并将更改正确保存到数据库?
答案 0 :(得分:2)
我的猜测是你正在尝试复制的外键关系(最初没有加载)(因为延迟加载)在复制期间,它正在尝试加载它,但DataContext已经被处理掉了。
我一直在研究类似的问题。我最终使用AutoMapper处理复制属性。我已将AutoMapper配置为忽略主键字段以及任何关系。类似的东西:
public void Update(User user)
{
using (var db = new DataContext(...))
{
var userFromDb = db.Users.Where(x => x.Id == user.Id).Single();
AutoMapper.Mapper.Map(user, userFromDb);
db.SubmitChanges();
}
}
我的自动播放器配置类似于
AutoMapper.Mapper.Create<User, User>().ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.SomeRelation, opt => opt.Ignore());
您可以在此处找到AutoMapper:http://automapper.codeplex.com/
答案 1 :(得分:0)
我让我的回购非常精益,唯一的工作就是与数据库进行交互。我在repo之上构建了一个Service层,它可以做更多的工作
public class EventRepository : IEventRepository
{
private DBDataContext dc;
public EventRepository()
{
dc = new DBDataContext();
}
public void Create(Event @event)
{
dc.Events.InsertOnSubmit(@event);
}
public System.Linq.IQueryable<Event> Read()
{
object events = (from e in dc.Eventse);
return events.AsQueryable;
}
public void SubmitChanges()
{
dc.SubmitChanges();
}
}
然后来自服务层的相应调用看起来像这个
public void AddEvent(Event @event)
{
_EventRepository.Create(@event);
}
public void SubmitChanges()
{
_EventRepository.SubmitChanges();
}
我从我的控制器那里打电话。
// AutoMapper will allow us to map the ViewModel with the DomainModel
Mapper.CreateMap<Domain.ViewModels.EventsAddViewModel, Domain.Event>();
object @event = Mapper.Map<Domain.ViewModels.EventsAddViewModel, Domain.Event>(eventToAdd);
// Add the event to the database
EventService.AddEvent(@event);
EventService.SubmitChanges();