2011-01-30 151 views
1

這裏有大量的信息,但即使在閱讀了幾個小時和幾個小時之後,我似乎也無法按照我想要的方式工作。Linq to Sql - 如何使用存儲庫模式更新對象?

我試圖更新一個用戶對象,通過傳遞一個用戶對象,並一般地比較用戶對象的變化,我拉出數據庫。我總是最後使用此方法時得到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對象的所有更改。

我也對樂觀併發做了一些閱讀,並在數據類型時間戳表中添加了一列,但這似乎也沒有任何影響。

我究竟在做什麼錯在這裏?

我怎樣才能得到這個一般性地檢測到什麼已經改變,並正確地堅持對數據庫的更改?

回答

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配置是一樣的東西

AutoMapper.Mapper.Create<User, User>().ForMember(dest => dest.Id, opt => opt.Ignore()) 
             .ForMember(dest => dest.SomeRelation, opt => opt.Ignore()); 

你可以在這裏找到AutoMapper:http://automapper.codeplex.com/

+0

這看起來不錯,但我建議使用`SubmitChanges()`作爲自己的方法。通過這種方式,您可以在提交數據之前堆積幾個數據庫調用。 – 2011-01-30 00:23:56

+0

是的,我完全同意SubmitChanges()它自己的方法。以上只是該模式的快速僞代碼。我也會讓我的資源庫將通用方法暴露給服務層。如果@Sgraffite願意,我可以擴展更多。 – mfanto 2011-01-30 00:45:13

0

我把我的回購很瘦,這是唯一的工作就是與數據庫交互。我建立了一個服務層上,做更多的工作

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(); 
相關問題