问题
I have an classic 3 layer project, that has these layers:
- UI (WinForm Project)
- BLL
- DAL(using EF codefirst)
My entities are disconnected POCO
s and I used them to pass data between layers and used them to bind to the UI controls.
I load a graph of some related entities to UI(e.g. Order
with it's OrderLine
s and Product
of each OrderLine
), user may add some new entities, edit some others and delete some others entities in this graph, and then send this graph to DAL to persist this changes to DB.
I want to All these CRUD operations apply in one transaction
. so, for this requirement, and because my POCO
s are disconnected, I used following State
enum
for my BaseEntity
class to keep its state in client side(all other entities inherited from BaseEntity
):
public enum States
{
Unchanged,
Added,
Modified,
Deleted
}
In DAL, when I want to persist this changed graph of objects, because this entity graph is disconnected from DbContext, I should attach root of my graph to the created DbContext and because after attaching the root to DbContext
state of all entries in the DbContext
will be Added
, I should sync State
of each Entry
in DbContext with State
of entities in my graph, so I used these methods to do this:
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);
}
}
As you see, I am doing a lot of stuff outside of EF and do not use EF features, because my POCOs are disconnected.
Is there any way to apply these bulk CRUD scenario, without disconnecting my POCO
s from DbContext
?
回答1:
For disconnected POCO entities I have followed this pattern when persisting.
- Get a connected entity graph from the db.
- Map the disconnected graph to the connected one.
- Persist the connected graph.
Currently you are attempting to track changes all the way up through the UI, when these changes may or may not be relevant by the time you are ready to persist, which is cumbersome at best. I have found that getting the most recent entity from the db just prior to persisting works out much better.
This also gives you the ability to check for concurrency issues when performing the mapping.
来源:https://stackoverflow.com/questions/20478439/crud-operations-with-connected-pocos-instead-of-disconnected-pocos-in-ef-code-fi