2012-01-24 15 views
4

編輯:ANSWER AT BOTTOM這個問題EF代碼第一次通用檢查是否存在沒有公共ID屬性的對象?

好了,所以我有一些通用的EF功能(其中大部分我都從這裏得到),但他們似乎並不管用。

我有3類:

public class Group : Entity 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public virtual GroupType GroupType { get; set; } 

    public virtual ICollection<User> Users { get; set; } 
} 
public class GroupType: Entity 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
} 

public class User: Entity 
{ 
    public Guid Id { get; set; } 
    public string FirstName { get; set; } 
    public string MiddleName { get; set; } 
    public string LastName { get; set; } 
    public string UserName { get; set; } 

    public virtual ICollection<Group> Groups { get; set; } 
} 

我的CRUD操作:

public void Insert(TClass entity) 
    { 
     if (_context.Entry(entity).State == EntityState.Detached) 
     { 
      _context.Set<TClass>().Attach(entity); 
     } 
     _context.Set<TClass>().Add(entity); 
     _context.SaveChanges(); 
    } 

public void Update(TClass entity) 
    { 
     DbEntityEntry<TClass> oldEntry = _context.Entry(entity); 

     if (oldEntry.State == EntityState.Detached) 
     { 
      _context.Set<TClass>().Attach(oldEntry.Entity); 
     } 

     oldEntry.CurrentValues.SetValues(entity); 
     //oldEntry.State = EntityState.Modified; 

     _context.SaveChanges(); 
    } 

public bool Exists(TClass entity) 
    { 
     bool exists = false; 

     if(entity != null) 
     { 
      DbEntityEntry<TClass> entry = _repository.GetDbEntry(entity); 
      exists = entry != null; 
     } 

     return exists; 
    } 

public void Save(TClass entity) 
    { 
     if (entity != null) 
     { 
      if (Exists(entity)) 
       _repository.Update(entity); 
      else 
       _repository.Insert(entity); 
     } 
    } 

最後我打電話這段代碼在下面的方法:

public string TestCRUD() 
    { 

     UserService userService = UserServiceFactory.GetService(); 
     User user = new User("Test", "Test", "Test", "TestUser") { Groups = new Collection<Group>() }; 

     userService.Save(user); 
     User testUser = userService.GetOne(x => x.UserName == "TestUser"); 

     GroupTypeService groupTypeService = GroupTypeServiceFactory.GetService(); 
     GroupType groupType = new GroupType("TestGroupType2", null); 

     groupTypeService.Save(groupType); 

     GroupService groupService = GroupServiceFactory.GetService(); 
     Group group = new Group("TestGroup2", null) { GroupType = groupType }; 
     groupService.Save(group); 

     user.Groups.Add(group); 
     userService.Save(user); 

     return output; 
    } 

當我到:

user.Groups.Add(group); 
userService.Save(user); 

我收到以下錯誤:

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

用下面的內部異常:

The INSERT statement conflicted with the FOREIGN KEY constraint "User_Groups_Source". The conflict occurred in database "DBNAME", table "dbo.Users", column 'Id'.

的問題:

1)Exists始終即使剛創建的實體返回true在內存中,因此插入實際上只是Update內部的Save方法,我猜這是因爲我不理解DbE ntityEntry完全是因爲它本身和Entry.Entity都不爲null。我如何檢查存在? 2)即使所有代碼都在TestCRUD中運行,直到最後,這些實體都沒有實際保存到數據庫中。我很積極我的數據庫設置正確,因爲我的自定義初始化程序正在刪除並始終重新創建數據庫,並且每次都插入種子數據。這可能是因爲更新總是被稱爲編號1中提到的。

任何想法如何解決?

編輯:ANSWER

由於假定,問題是Exists所以插入從來沒有被稱爲總是返回true。我解決了這個問題,通過使用反射來獲取主鍵和插入到這find方法來獲得存在像這樣:

public bool Exists(TClass entity) 
    { 
     bool exists = false; 

     PropertyInfo info = entity.GetType().GetProperty(GetKeyName()); 
     if (_context.Set<TClass>().Find(info.GetValue(entity, null)) != null) 
      exists = true; 

     return exists; 
    } 

所有其他方法如預期開始工作。但是,我上了同一線路不同的錯誤:

user.Groups.Add(group); 
userService.Save(user); 

這是:

Violation of PRIMARY KEY constraint 'PK_GroupTypes_00551192'. Cannot insert duplicate key in object 'dbo.GroupTypes'. The statement has been terminated.

我將發佈,作爲一個新的問題,因爲它是一個新的錯誤,但它確實解決了第一個問題。

+0

將實體附加到上下文後,應將其狀態設置爲添加或修改。請參閱ObjectStateManager.ChangeObjectState方法。 但不能說爲什麼你的Exists方法在保存用戶之前給你的真實。 – ElDog

+0

@ElDog我試過了(你可以看到它在更新中註釋掉了),並且拋出一個錯誤,說不能這樣做,因爲實體在操作之間被修改或刪除,或者出現這種情況。 – SventoryMang

回答

1

How can I check for an exists?

我通常看到有人檢查一個實體是否已經存在的方式是,通過檢查其Id屬性是否大於零。您應該能夠使用其上的Id屬性或(如果您希望實體具有多個關鍵屬性)的接口,您可以讓每個實體覆蓋抽象基類,覆蓋Exists屬性以檢查其自身的ID屬性非默認值。或者您可以使用反射自動查找ID屬性或屬性,as explained here

我懷疑剩下的問題會消失,一旦你正確地插入新項目,而不是嘗試更新它們。

+0

有沒有其他辦法一般這樣做?是的,我在這裏發佈了這個確切的問題:http://stackoverflow.com/questions/8948815/entity-framework-generic-compare-type-without-id,並嘗試了答案,似乎沒有工作。 – SventoryMang

+0

問題是一些實體具有一個int ID,其prop名稱爲classnameId,而其他實體具有prop id名稱的guid。要在通用方法中使用任何ID,他們必須實現相同的基類/接口,但是如何才能使兩個接口都可以實現? – SventoryMang

+0

嗯好吧,我會看看我是否可以使用它來獲得工作。 – SventoryMang

相關問題