gpt4 book ai didi

c# - 如何停止尝试更改 entitykey 值的 dbentityentry.currentvalues.setvalues

转载 作者:行者123 更新时间:2023-11-30 16:17:55 24 4
gpt4 key购买 nike

我正在使用以下代码使用从我的代码中收集的新信息更新实体对象。我正在使用 Entity Framework 5

我使用以下扩展方法(作为我过去在 EF4 中使用的重新附加代码的替代方法):

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

问题是,当调用此方法时,SetValues 方法会尝试修改附加对象上的 EntityKey 值(显然我不希望它这样做)所以它会抛出一个错误。

我想这里有两个问题:

  1. 有没有办法阻止它尝试更新键值?

  2. 如果不是,我该如何复制过去在 EF4 中正常工作的 ObjectContext.ApplyCurrentValues() 代码?

----更新----

我之前用于EF4的代码如下:

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;
}
}

最佳答案

在我看来,这个异常表明您的调用代码有问题 - 或者至少不正常。

currentObject 是一个附加实体,而 sourceObject 是(通常)一个分离的对象(不一定是实体),应该具有相同的键值(或没有键属性全部)。

确实,设置当前值与 DbContext 的工作方式不同,因为您必须显式提供当前附加的实体才能更新其当前值。使用 ObjectContextApplyCurrentValues 您不提供此实体:

objectContext.ApplyCurrentValues("MyEntitySet", sourceObject);

这是不同的,因为...

  • sourceObject 必须是实体,不能是任意的object
  • 它更新与 sourceObject 具有相同键值的附加实体的值

在您的示例中,它会更新 currentObject 之外的另一个实体,因为 currentObject 显然不是与 sourceObject 具有相同键的实体。

如果您使用了 ObjectStateEntry.ApplyCurrentChanges(它更接近于 DbContext 中的新版本),您将得到相同的异常:

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

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

EF 会在这里提示您尝试更改键值。如果 sourceObjectcurrentObject 的类型不同,它会提示,而 DbContext 会允许(这使得过程与 DbContext 在我看来更有用,因为您可以使用具有匹配属性名称的任意对象(例如 DTO)来更新实体)。

编辑

重现您在 EF 4 中使用的方法的主要问题是具有 EF 5/DbContext 的实体不是从 EntityObject 派生的,而是 POCO。因此,您没有可用的 EntityKey 来允许此方法的通用实现。

您可以做的是引入一个标记实体关键属性的接口(interface),例如:

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

您的实体类将实现此接口(interface),例如 Order 实体:

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

您可以为此接口(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;
}

如果您的实体并不总是具有 int 属性 Id 但它们的键具有不同的类型、名称或者可以是复合的,那么传递实体的键进入方法而不是使用接口(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;
}

关于c# - 如何停止尝试更改 entitykey 值的 dbentityentry.currentvalues.setvalues,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16646922/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com