如何阻止 dbentityentry.currentvalues.setvalues 尝试更改实体键值

2024-03-10

我正在使用以下代码使用从我的代码收集的新信息来更新实体对象。我在用实体框架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. 如果不是,我该如何复制ObjectContext.ApplyCurrentValues()以前在 EF4 中运行良好的代码?

- - 更新 - -

我之前用于 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因为您必须显式提供当前附加实体才能更新其当前值。使用ApplyCurrentValues of ObjectContext您不提供该实体:

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 会在这里抱怨您尝试更改键值。它会抱怨如果sourceObject与以下类型不同currentObject while DbContext将允许(这使得程序DbContext在我看来更有用,因为您可以使用具有匹配属性名称的任意对象(例如 DTO)来更新实体)。

Edit

重现您使用 EF 4 的方法的主要问题是使用 EF 5/ 的实体DbContext不源自EntityObject但都是 POCO。因为这个你没有EntityKey可用,将允许此方法的通用实现。

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

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

您的实体类将实现此接口,例如Order entity:

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

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

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但它们的键具有不同的类型、名称或者可以是复合的,这可能是将实体的键传递到方法中而不是使用接口的更简单的方法:

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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何阻止 dbentityentry.currentvalues.setvalues 尝试更改实体键值 的相关文章

随机推荐

  • XMPPFramework - 如何注册新用户帐户

    我正在尝试使用 XMPPFramework 连接到 Openfire 服务器并创建一个新的用户帐户 如果我已经以其他用户身份登录 此代码将创建一个新的用户帐户 NSXMLElement query NSXMLElement elementW
  • 手动将 UITabBar 添加到 UITableViewController

    我有一个标准应用程序 带有管理多个 UITableViewController 类的导航控制器 我想将 UITabBar 添加到根视图 UITableViewController 来管理过滤 UITableView 中显示的对象的选择 我不
  • 如何刷新表中的单行?

    是否可以刷新a的单行vaadin table成分 到目前为止 如果表行编辑完成 我只需刷新整个表 table refreshRowCache 但这可能会导致稍后的大型表出现性能问题 那么 如何刷新单行呢 我在 Vaadin 论坛上发现了这个
  • Array.delete(object) 从数据库中删除?

    所以我试图获取一系列不包含 post 的帖子 令我惊讶的是 下面的代码导致 post 被从数据库中删除 post Post find 2 posts Post where text gt title posts delete post 为什
  • Android onNewIntent() 通知未正确执行

    我有一个用于通知的广播接收器 我的应用程序是一个 webkit 我希望当用户单击通知时打开我的应用程序并定向到某个 URL 一切似乎都工作正常 但我现在遇到了问题 onNewIntent 如果用户上次通过按主页按钮退出应用程序 则调用此方法
  • 相机标定opencv

    你好 我正在做一个项目来进行图像 3D 重建 我正在校准相机的阶段 这需要很长时间才能完成 但是当我编译代码并在相机前显示棋盘时 它会直接进入未处理的异常错误 当图片不在框架中时 一旦进入框架就没有错误 出现未处理的错误我不知道为什么 我问
  • ActiveJob Deliver_later 不发送

    我有以下方法 UserMailer comment alert comment user type deliver later 奇怪的是 它与参数一起出现deliver now在 Rails 日志中 ActiveJob Enqueued A
  • 如何在 Kotlin DSL 中有条件地接受 Gradle 构建扫描插件服务条款?

    这基本上延伸了这个问题 https stackoverflow com q 52636622 1127485使用 Kotlin DSL 而不是 Groovy DSL 如何Groovy DSL 解决方案 https stackoverflow
  • 将 ASP.net Core 2.0 部署到 Azure

    我已通过以下步骤将 ASP net Core 1 1 应用程序升级到 ASP net Core 2 0 将目标框架更改为2 0 升级所有 Nuget 包 现在 我从 git 进行的自动部署运行并显示成功 但应用程序未运行 我收到以下错误 H
  • R,dplyr - group_by()和arrange()的组合不会产生预期的结果?

    使用 dplyr 函数时group by 紧接着arrange 我希望得到数据帧已排序的输出within我所说的组group by 我对文档的阅读是 这种组合应该产生这样的结果 但是当我尝试时 这不是我得到的 并且谷歌搜索并没有表明其他人遇
  • 将 Boost 适配器与 C++11 lambda 结合使用

    我尝试编译这段代码 include
  • 虚拟继承混乱

    我正在阅读有关继承的内容 并且有一个主要问题 我几个小时都无法解决 给定一个类Bar是一个类virtual功能 class Bar virtual void Cook 两者有什么不同 class Foo public Bar virtual
  • CollectionView 内的按钮不可点击

    我在集合视图的自定义单元格中有一个按钮 集合视图位于滚动视图上 由于某种原因 我无法单击该按钮 我已检查我的所有元素是否都启用了用户交互 Here is my layout of the collection I ve hidden som
  • XSLT:通过递增属性和值生成多个对象

    我有一个如下所示的 xml 我想复制 n 次 同时递增其元素之一和属性之一 XML 输入
  • 使用鼻子进行测试的 Python 导入 - 导入当前包之上的模块的最佳实践是什么

    这是一个经常以不同形式被问到的问题 并且经常得到 哈哈 你做得不对 的回答 很确定这是因为人们 包括我 尝试使用一个常识性场景作为实现 并且解决方案并不明显 如果您以前没有这样做过 会接受 让飞出瓶子 的答案 Given project i
  • 为什么Delete既是DDL又是DML语句

    我目前正在阅读 Microsoft 官方书籍 数据库管理基础知识 准备参加考试 我了解 DDL 和 DML 是什么 但 Microsoft 将 DELETE 显示为 DDL 和 DML 语句 我已经用谷歌搜索过这一点 但我无法证实或否认这一
  • 关于weak_ptr的线程安全性

    std shared ptr
  • 使用 Java 进行 AWS S3 文件搜索

    我们使用 java 类从 AWS s3 存储桶下载文件 代码如下 inputStream AWSFileUtil getInputStream AWSConnectionUtil getS3Object null cdn generalse
  • 从 Java 应用程序调用 Servlet

    我想从 Java 应用程序调用 Servlet 问题是 该调用似乎没有到达 Servlet 我没有收到任何错误 但没有到达 Servlet 中的第一个输出 doPost 如果我在网络浏览器中打开 URL 我当然会得到不支持 GET 等错误
  • 如何阻止 dbentityentry.currentvalues.setvalues 尝试更改实体键值

    我正在使用以下代码使用从我的代码收集的新信息来更新实体对象 我在用实体框架5 我使用以下扩展方法 作为我在 EF4 中使用的重新附加代码的替代方法 public static void ApplyValues this object cur