如何停止dbentityentry.currentvalues.setvalues试图改变的EntityKey值 [英] how to stop dbentityentry.currentvalues.setvalues trying to change entitykey value

查看:1066
本文介绍了如何停止dbentityentry.currentvalues.setvalues试图改变的EntityKey值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用下面的代码更新从我的代码收集到的新的信息的实体对象。我使用的实体框架5



我用下面的扩展方法(作为替代我以前在EF4使用重新附加代码)

 公共静态无效ApplyValues(此对象currentObject,对象sourceObject,System.Data.Entity.DbContext OBJ)
{
obj.Entry(currentObject).CurrentValues.SetValues(sourceObject);
}

的问题是,当这种方法被称为 setValues方法方法试图修改附加的对象上的的EntityKey 值(很明显,我不希望它做到这一点),所以它抛出一个错误。



我想这里有两个问题:




  1. 有的方式,以防止它试图更新密钥值?


  2. 如果不是我怎么复制过去可以正常工作的罚款 ObjectContext.ApplyCurrentValues()代码EF4?




---- ----更新



我以前的代码,我用EF4如下:

 公共静态System.Data这.Objects.DataClasses.EntityObject重新连接(这System.Data.Objects.ObjectContext OBJ,System.Data.Objects.DataClasses.EntityObject objectDetached)
{
如果(objectDetached.EntityKey!= NULL)
{
对象原有= NULL;
如果(obj.TryGetObjectByKey(objectDetached.EntityKey,出原件))
{
objectDetached = obj.ApplyCurrentValues(objectDetached.EntityKey.EntitySetName,objectDetached);
返回objectDetached;
}
,否则
{
抛出新ObjectNotFoundException();
}
}
,否则
{
返回objectDetached;
}
}


解决方案

在我认为这个异常指示,什么是错的 - 或者至少是不寻常的 - 在你的调用代码



currentObject 是附加的实体,而 sourceObject 是(通常)分离对象(不一定是实体)应具有相同的关键值(或无键属性在所有)。



事实上与的DbContext 设定电流值的工作方式不同,因为你必须以更新其当前明确提供电流连接实体值。使用 ApplyCurrentValues 的ObjectContext 你不提供这个实体的:

  objectContext.ApplyCurrentValues(MyEntitySet,sourceObject); 

这是不同的,因为...




  • sourceObject 必须是一个实体,并且不能是任意对象

  • 它更新具有相同的密钥值 sourceObject

$ b $连接的实体的值b

在你的榜样,因为很明显 currentObject 是不是会更新比 currentObject 另一个实体实体具有相同的密钥 sourceObject



如果您已经使用 ObjectStateEntry.ApplyCurrentChanges (这是的DbContext 更接近新版本),你会得到相同的异常:

  VAR的ObjectContext =((IObjectContextAdapter)OBJ).ObjectContext; 

VAR进入= objectContext.ObjectStateManager.GetObjectStateEntry(currentObject);
entry.ApplyCurrentValues(sourceObject);



EF会抱怨在这里,你试图改变键值。它会抱怨,如果 sourceObject 是同一类型 currentObject 不同时,的DbContext 将允许(这使得该过程与的DbContext 在我看来,更有用,因为你可以使用任意对象相匹配的属性名称 - 例如DTO的 - 更新实体)。



修改



再现方法的主要问题你曾与EF 4采用的是与EF 5实体/ 的DbContext 不会从 EntityObject 导出,但波苏斯。正因为如此,你没有一个的EntityKey 可用的将允许通用实现此方法。



什么你可以做的是引入标志着你的实体的关键属性,像这样如一个接口:

 公共接口IEntity 
{
INT标识{搞定;组; }
}

您实体类将实现这个接口,比如一个订单实体:

 公共类订单:IEntity 
{
公众诠释标识{搞定;组; }
公众的DateTime ShippingDate {搞定;组; }
//等
}

您可以创建一个通用的方法这个接口的约束:

 公共静态牛逼重新连接< T>(的DbContext背景下,T objectDetached)
,其中T :类,IEntity
{
科技原创= context.Set< T>()找到(objectDetached.Id);
如果(原== NULL)
抛出新ObjectNotFoundException();

context.Entry(原件).CurrentValues.SetValues(objectDetached);

返回objectDetached;
}

如果您的实体并不总是有一个 INT 属性编号,但它们的键有不同的类型,名称或者可能是复合的很可能是在实体的钥匙插入方法传递,而不是更简单的方法使用接口:

 公共静态牛逼重新连接< T>(的DbContext背景下,T objectDetached,
params对象[]键值),其中T:类
{
科技原创= context.Set< T>()找到(键值);
如果(原== NULL)
抛出新ObjectNotFoundException();

context.Entry(原件).CurrentValues.SetValues(objectDetached);

返回objectDetached;
}


I am using the following code to update an entity object with the new information gathered from the my code. I am using Entity Framework 5.

I use the following extension method (as a alternative to the reattach code I used to use in EF4):

public static void ApplyValues(this object currentObject, object sourceObject, System.Data.Entity.DbContext obj)
{
  obj.Entry(currentObject).CurrentValues.SetValues(sourceObject);
}

The problem is that when this method is called the SetValues method tries to modify the EntityKey value on the attached object (obviously I do not want it to do this) and so it throws an error.

I suppose there are two questions here:

  1. Is there a way to prevent it from trying to update the key value?

  2. if not how do I replicate the ObjectContext.ApplyCurrentValues() code that used to work fine in EF4?

----UPDATE----

My previous code I used for EF4 is as follows:

public static System.Data.Objects.DataClasses.EntityObject ReAttach(this System.Data.Objects.ObjectContext obj, System.Data.Objects.DataClasses.EntityObject objectDetached)
{
    if (objectDetached.EntityKey != null)
    {
        object original = null;
        if (obj.TryGetObjectByKey(objectDetached.EntityKey, out original))
        {
            objectDetached = obj.ApplyCurrentValues(objectDetached.EntityKey.EntitySetName, objectDetached);
            return objectDetached;
        }
        else
        {
            throw new ObjectNotFoundException();
        }
    }
    else
    {
        return objectDetached;
    }
}

解决方案

In my opinion this exception indicates that something is wrong - or at least unusual - in your calling code.

currentObject is an attached entity while sourceObject is (normally) a detached object (not necessarily an entity) that should have the same key values (or no key properties at all).

Indeed setting the current values works differently with DbContext because you have to supply the current attached entity explicitly in order to update its current values. Using ApplyCurrentValues of ObjectContext you don't supply this entity:

objectContext.ApplyCurrentValues("MyEntitySet", sourceObject);

This is different because...

  • sourceObject must be an entity and cannot be an arbitrary object
  • it updates the values of the attached entity that has the same key values as sourceObject

In your example it would update another entity than currentObject because apparently currentObject is not the entity that has the same key as sourceObject.

If you have used ObjectStateEntry.ApplyCurrentChanges (which is closer to the new version in DbContext) you would get the same exception:

var objectContext = ((IObjectContextAdapter)obj).ObjectContext;

var entry = objectContext.ObjectStateManager.GetObjectStateEntry(currentObject);
entry.ApplyCurrentValues(sourceObject);

EF will complain here that you try to change the key values. And it will complain if sourceObject is not of the same type as currentObject while DbContext would allow that (which makes the procedure with DbContext more useful in my opinion because you can use arbitrary objects with matching property names - for example DTOs - to update the entity).

Edit

The main problem to reproduce the method you have used with EF 4 is that entities with EF 5/DbContext don't derive from EntityObject but are POCOs. Because of this you don't have an EntityKey available that would allow a generic implementation of this method.

What you could do is to introduce an interface that marks the key property of your entities, like so for example:

public interface IEntity
{
    int Id { get; set; }
}

Your entity classes would implement this interface, for instance an Order entity:

public class Order : IEntity
{
    public int Id { get; set; }
    public DateTime ShippingDate { get; set; }
    // etc.
}

You could create a generic method with a constraint for this interface:

public static T ReAttach<T>(DbContext context, T objectDetached)
    where T : class, IEntity
{
    T original = context.Set<T>().Find(objectDetached.Id);
    if (original == null)
        throw new ObjectNotFoundException();

    context.Entry(original).CurrentValues.SetValues(objectDetached);

    return objectDetached;
}

If your entities do not always have an int property Id but their keys have different types, names or could be composite it is probably the easier way to pass in the entity's key into the method instead of using an interface:

public static T ReAttach<T>(DbContext context, T objectDetached,
    params object[] keyValues) where T : class
{
    T original = context.Set<T>().Find(keyValues);
    if (original == null)
        throw new ObjectNotFoundException();

    context.Entry(original).CurrentValues.SetValues(objectDetached);

    return objectDetached;
}

这篇关于如何停止dbentityentry.currentvalues.setvalues试图改变的EntityKey值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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