服务器端的自我跟踪实体 - MergeOption.No跟踪可行的解决方案? [英] Self Tracking Entities on the server side - MergeOption.NoTracking a viable solution?

查看:90
本文介绍了服务器端的自我跟踪实体 - MergeOption.No跟踪可行的解决方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我一直在努力寻找一个问题的解决方案,默认情况下自我跟踪实体在服务器端的行为与在客户端上的行为不同。

我想要达到的目标是,例如<

Hi,

I have been working on finding a solution to the problem that Self Tracking entities by default do not behave the same on the server side as they do on the client.

What I would like to achieve is that something like

var repository = ServiceLocator.Current.GetInstance<IRepository<Device>>();

var device = repository.Single(a => a.IdenficationNumber == "xyz", a => a.DeviceData);

device.DeviceData[0].MarkAsDeleted(); (A)

var res = repository.Save(device, true);


 
实际上会导致删除DeviceData子项,无论是否在服务器或客户端上执行标有(A)的行。

但是上述代码不会删除该子项,因为ObjectContext永远不会知道更改。

所涉及的各种元素的代码如下,我只包括我希望足以理解其工作原理,实际代码有点不同但不需要用这个例子弄乱这个例子。 />

 
will actually result in the DeviceData child to be deleted, regardless of whether the line marked with (A) is executed on the server or the client.

However the above code will not delete that child as the ObjectContext will never get to know about the change.

The code for the various elements involved is as follows, I am only including what I hope is enough to understand the workings, the actual code i a little different but no need to clutter the example with that.

public class BasicRepository<T> : IRepository<T> where T : class
{
    protected ObjectSet<T> ObjectSet
    {
        get
        {
            return _objectSet ?? (_objectSet = _context.CreateObjectSet<T>());
        }
    }
    
    public T Single(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includes)
    {
        var set = (ObjectQuery<T>)this.ObjectSet;
        foreach(var exp in includes)
        {
            set = set.Include(exp);
        }

        return set.Single<T>(where);
    }
    
    public Result<EntityValidationMessage> Save(T entity, bool endUnitOfWork = false)
    {
        this.ObjectSet.ApplyChanges(entity);
        this.Context.DetectChanges();
            
        //Get changes for the object graph
        var changedEntities = from entry in _context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted)
                              where entry.Entity != null
                              select entry;
        //Do validation
        ...
        
        if (endUnitOfWork)
        {
            _context.SaveChanges();
        }
    }
}



在第一部分执行保存时,会看到 changedEntities 没有项目,即没有检测到删除。

经过一些反复试验后,我想出了一个可能的解决方案,我想知道它是否可行。我确信我已经错过了一些警告。
解决方案只是不将返回的entites附加到ObjectContext并且仅仅依赖于实体本身的自我跟踪能力。

所以代码看起来像这样(我已经在存储库中省略了那些未更改的方法)



When executing the save in the first section one will see that changedEntities contains no items, i.e. the deletion has not been detected.

After a bit of trial and error I came up with a possible solution, and I would like to know if it is viable or not. I am sure I have missed some caveats.
The solution is simply to not attach the returned entites to the ObjectContext and rely solely on the Self Tracking abilities of the entity itself.

So the code looks like this instead (I have left out those methods on the repository that are unchanged)

var repository = ServiceLocator.Current.GetInstance<IRepository<Device>>();

var device = repository.Single(a => a.IdenficationNumber == "xyz", a => a.DeviceData);
device.StartTracking(); // <= Change

device.DeviceData[0].MarkAsDeleted();

var res = repository.Save(device, true);

public class BasicRepository<T> : IRepository<T> where T : class
{
    protected ObjectSet<T> ObjectSet
    {
        get
        {
            if (_objectSet == null)
            {
                _objectSet = _context.CreateObjectSet<T>();
                _objectSet.MergeOption = MergeOption.NoTracking;
            }

            return _objectSet;
        }
    }
}


 
就我的测试而言,它似乎按照我想要的方式工作。

我想做的一件事就是自动为我调用StartTracking(),因为这显然是必需的。有没有一种简单的方法可以实现这一目标(主要是在收集回收的情况下,单个参与者显然非常简单)?
再次最重要的是,我错过了一些使这种方法不可行的理解?

谢谢,
Thomas Scheelhardt

 
As far as my tests go this far, it seems to work the way I want.

One thing I would like to do though is to have StartTracking() called for me automatically, since that is obviously required. Is there an easy way I can achieve that (mainly in the case of collections being returned, single entites are clearly simple enough)?

And again most importantly, am I missing some understanding that makes this approach unviable?


Thanks,
Thomas Scheelhardt

推荐答案

你可能会写一个ObjectMaterialized事件的处理程序并使用它打开更改跟踪...

You could probably write a handler for the ObjectMaterialized event and use it to turn on change tracking...

- Danny

- Danny


这篇关于服务器端的自我跟踪实体 - MergeOption.No跟踪可行的解决方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆