Mas*_*oud 5 c# entity-framework poco ef-code-first dbcontext
我首先使用EF代码开发我的3层WinForm应用程序,我使用了断开连接的POCO
s作为我的模型实体.我的所有实体都是从BaseEntity
类继承的.
我使用了断开连接的POCO
s,所以我State
在客户端处理实体,并且在ApplyChanges()
方法中,我将我的实体图(例如An Order
with it's OrderLines
and Products
)附加到我DbContext
,然后将每个实体State
与它的客户端同步State
.
public class BaseEntity
{
int _dataBaseId = -1;
public virtual int DataBaseId // DataBaseId override in each entity to return it's key
{
get { return _dataBaseId; }
}
public States State { get; set; }
public enum States
{
Unchanged,
Added,
Modified,
Deleted
}
}
Run Code Online (Sandbox Code Playgroud)
所以,当我想保存相关实体的图形时,我使用了以下方法:
public static EntityState ConvertState(BaseEntity.States state)
{
switch (state)
{
case BaseEntity.States.Added:
return EntityState.Added;
case BaseEntity.States.Modified:
return EntityState.Modified;
case BaseEntity.States.Deleted:
return EntityState.Deleted;
default:
return EntityState.Unchanged;
}
}
public void ApplyChanges<TEntity>(TEntity root) where TEntity : BaseEntity
{
_dbContext.Set<TEntity>().Add(root);
foreach (var entry in _dbContext.ChangeTracker
.Entries<BaseEntity>())
{
BaseEntity stateInfo = entry.Entity;
entry.State = ConvertState(stateInfo.State);
}
}
Run Code Online (Sandbox Code Playgroud)
但是如果我的图包含2个或更多具有相同键的实体,则会出现此错误:
An object with the same key already exists in the ObjectStateManager...
Run Code Online (Sandbox Code Playgroud)
如何在我的图形(root
)中检测具有相同键的实体并使其在我的ApplyChanges()
方法中是唯一的?
我改变了我BaseEntity
的
public class BaseEntity
{
public int Id {get; set;}
public States State { get; set; }
public bool MustDelete {get; set;}
public enum States
{
Unchanged,
Added,
Modified,
Deleted
}
}
Run Code Online (Sandbox Code Playgroud)
并且还更改了我的 BaseDomainService<T>
班级中的以下方法:
public class BaseDomainService<T> where T : class
{
protected readonly DbContext _dbContext;
public BaseDomainService(IUnitOfWork uow)
{
_dbContext = (DbContext)uow;
}
.....
public static EntityState ConvertState(BaseEntity.States state)
{
switch (state)
{
case BaseEntity.States.Added:
return EntityState.Added;
case BaseEntity.States.Modified:
return EntityState.Modified;
case BaseEntity.States.Deleted:
return EntityState.Deleted;
default:
return EntityState.Unchanged;
}
}
public void ApplyChanges<TEntity>(TEntity root) where TEntity : BaseEntity
{
_dbContext.Set<TEntity>().Add(root);
foreach (var entry in _dbContext.ChangeTracker
.Entries<BaseEntity>())
{
if (FoundAnEntityWithSameKeyInDbContext<TEntity>(entry))
entry.State = EntityState.Detached;
else
{
BaseEntity stateInfo = entry.Entity;
if (stateInfo.MustDelete == true)
entry.State = EntityState.Detached;
else
entry.State = ConvertState(stateInfo.State);
}
}
}
private bool FoundAnEntityWithSameKeyInDbContext<TEntity>(DbEntityEntry<BaseEntity> entry) where TEntity : BaseEntity
{
var tmp = _dbContext.ChangeTracker.Entries<BaseEntity>().Count(t => t.Entity.Id == entry.Entity.Id && t.Entity.Id != 0 && t.Entity.GetType() == entry.Entity.GetType());
if (tmp > 1)
return true;
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
那么,问题就解决了。