开发者

How to do update a new record before it is committed in EF4?

开发者 https://www.devze.com 2023-02-17 15:56 出处:网络
I\'m using EF4 POCOs and UnitOfWork/repository patterns with MVC 3.I\'m trying to understand how I would modify a new record that is to be inserted.

I'm using EF4 POCOs and UnitOfWork/repository patterns with MVC 3. I'm trying to understand how I would modify a new record that is to be inserted.

My service method to insert/update looks something like this (the repository is injected in the service constructor via IoC):

public void UpdateData(Guid id, int newValue)
{
    MyPoco poco = _repository.FirstOrDefault(p => p.Id = id);

    if (poco == null)
    {
        poco = new Poco 
        {
            //set properties
        };

        _repository.Add(poco);
    }

    poco.SomeFieldToUpdate = newValue;
}

And my changes get persisted via my UnitOfWork on a UseUnitOfWorkAttribute action filter on my controller:

void IResultFilter.OnResultExecuted(ResultExecutedContext filterContext)
{
    var unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>();
    unitOfWork.Commit();
}

Of course, this works fine if this is ever hit just once, for existing or new data. And it works fine on multiple passes if it already exists.

But if the Guid value doesn't exist in the table, then it tries to do multiple inserts if this is called multiple times.

So that's my dilemma. I understand why this doesn't work, I'm just not sure the proper way to fix it. Basically, I need to somehow get a reference to the existing POCO in the UnitOfWork, and somehow update it. But the UnitOfWork is not available in my service (by design) -- and I'm not even sure I know how to pull an entity out of the UoW and update it anyway.

Am I going about this wrong or am I overlooking something simple here? Or do I have a fundamental flaw in how I've designed this? I have a开发者_开发知识库 feeling I may be making this harder than it should be.

Thanks in advance.


The reason why this happens is because your entity is not saved yet and you execute query to get it. Query will not find it in database and correctly return null.

You should not need to use repository / unit of work / ObjectContex as internal storage of not saved entities among service calls. If you need it you should check your application design and refactor it because something is probably wrong.

Anyway you can get not saved entity from context but it is not very nice code. You will need special method on your repository to get entity by id. You will use it instead of calling FirstOrDefault. Something like:

public MyPoco GetById(Guid id)
{
    MyPoco enity = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
        .Where(e => e.Entity != null && e.Entity.GetType() == typeof(MyPoco)))
        .Select(e => (MyPoco)e.Entity)
        .Where(p => p.Id == id)
        .SingleOrDefault();

    if (entity == null)
    {
        entity = context.MyPocos.FirstOrDefault(p => p.Id == id);
    }
}


Do you set the id you pass into UpdateData as the key on the new Poco object, like so:

poco = new Poco 
{
    Id = id;
    //set properties
};

If yes, you could query for the object not with FirstOrDefault but by using the TryGetObjectByKey in a repository method:

public Poco GetPocoByKey(Guid id)
{
    EntityKey key = new EntityKey("MyEntities.Pocos", "Id", id);
    object pocoObject;
    if (context.TryGetObjectByKey(key, out pocoObject))
        return (Poco)pocoObject;

    return null;
}

The advantage is that TryGetObjectByKey looks at first into the ObjectContext if it can find an object with the specified key. Only if not, then the database will be queried. Since you add the new Poco to the context the first time it isn't found, TryGetObjectByKey should find it in the context when you search for the object with the same key a second time, even if it has not been saved to the database yet.

Edit: This solution doesn't work!

Because TryGetObjectByKey does not find the key for objects which are in added state in the ObjectContext, even not if the key is not a DB generated key and supplied by the application (see comments below).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号