【问题标题】:How to copy all properties of an object to another in LINQ如何在LINQ中将对象的所有属性复制到另一个对象
【发布时间】:2014-02-10 05:13:32
【问题描述】:

我有一个 STUDENT 表对象,其中有新值,我想用这些新值更新 STUDENT 表。我的代码如下(用于将属性从 STD 复制到 getdata 但是)它没有更新数据库中 STUDENT 表中的值,为什么?先感谢您。

public void UpdateStudent(STUDENT STD)
    {
        context = new ERPDataContext();
        var getdata = context.STUDENTs.SingleOrDefault(obj=>obj.ID==STD.ID);
        getdata = STD;
        context.SubmitChanges();
    }

【问题讨论】:

  • 在使用引用类型时(在 C# 中,除了基本的 int、bool 等之外,几乎所有内容),将一种引用类型分配给另一种引用类型将有效地丢弃旧值。在你的情况下,你得到一个学生,然后把它扔掉并用你拥有的那个代替它,这与你告诉SubmitChanges()的上下文无关。

标签: c# linq asp.net-mvc-4


【解决方案1】:

您可以在此处使用反射。不太确定它是否会完全解决您的问题。使用反射也可能是一种矫枉过正,所以请检查性能。

我使用了一个虚拟类“A”来解释如何使用它。检查一下,让我知道它是否有效。

    public class A 
    {
        public string aField { get; set; }
    }

代码是:

        A obj1 = new A();
        A obj2 = new A();

        obj1.aField = "aaa";

        var propInfo = obj1.GetType().GetProperties();
        foreach (var item in propInfo)
        {
            obj2.GetType().GetProperty(item.Name).SetValue(obj2, item.GetValue(obj1, null), null);
        }

当然需要添加命名空间:

using System.Reflection;

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您必须手动更新所有属性:

    var getdata = context.STUDENTs.SingleOrDefault(obj=>obj.ID==STD.ID);
    getdata.Prop1 = STD.Prop1;
    getdata.Prop2 = STD.Prop2;
    context.SubmitChanges();
    

    否则,您只是替换 getdata 引用,不要更改对象本身。

    或者你可以使用以下:

    var getdata = context.STUDENTs.SingleOrDefault(obj=>obj.ID==STD.ID);
    var entry = context.Entry(getdata);
    entry.CurrentValues.SetValues(STD);
    entry.State = EntityState.Modified;
    context.SubmitChanges();
    

    【讨论】:

    • 行entry.CurrentValues.SetValues(STD);是否复制STD的所有属性并将其设置为getdata?
    • 什么是Entry()是c#什么的预定义函数?
    • 是的,这是DbContext上的一种方法。
    • @nowhewhomustnotbenamed。我刚刚发现了一篇非常好的文章:msdn.microsoft.com/en-us/data/jj592677.aspx
    • @MarcinJuraszek:谢谢 Marcin。确实是我一直在寻找学习使用 EF 的一个很好的链接
    【解决方案3】:

    以下是@samar 答案的变体,但内部部分用检查属性CanWrite 的if 包裹,否则会出错。

            A obj1 = new A();
        A obj2 = new A();
    
        obj1.aField = "aaa";
    
        var propInfo = obj1.GetType().GetProperties();
        foreach (var item in propInfo)
        {
           if(item.CanWrite)
           {
               obj2.GetType().GetProperty(item.Name).SetValue(obj2,   item.GetValue(obj1, null), null);
           }
        }
    

    更新了一个非常通用的辅助函数:

            protected void CopyEntityObject<T>(ref T old, ref T updated)
        {
            var propInfo = old.GetType().GetProperties();
            foreach (var item in propInfo)
            {
                if (item.CanWrite)
                {
                    old.GetType().GetProperty(item.Name).SetValue(old, item.GetValue(updated, null), null);
                }
            }
        }
    

    【讨论】:

    • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post。
    • Sbirthare,您必须有 50 名代表才能评论某人的回答。除了添加我自己的答案外,我没有其他方法可以添加我的信息。因此,我无法像我的回答中提到的那样直接向 samar 批评或要求澄清。
    • 没问题马克。我们感谢您的贡献。现在您的最新编辑看起来不错。
    【解决方案4】:

    您应该更改附加对象,在您的情况下是 getData 对象,然后调用提交更改。如果你想避免这种方法,你可以使用下面的代码:

    context.STUDENTs.Attach(STD);
    var entry = context.Entry(STD);
    context.SubmitChanges();
    

    您还可以更新已更改的属性:

    var getdata = context.STUDENTs.SingleOrDefault(obj=>obj.ID==STD.ID);
    getdata.Property = STD.Property;
    context.SubmitChanges();
    

    【讨论】:

    • 什么是“db.Entry()”?这是任何预定义的功能或东西吗?
    • 我把它改成了 context.Entry()。
    • 但是在这个项目中,我的智能感知中没有看到 .Entry(如果我只是输入它,它不会建议命名空间引用)
    • 你确定你使用的是EF 4+吗??
    【解决方案5】:

    由于您尝试用于更新值的STD 对象是一个实体类,我认为假设您已经发出查询、更改了一些数据并且现在希望将更改发送回数据库是合理的。

    如果是这样,使用反射来处理这就像使用大锤来破解坚果一样,并且手动更新每个属性将是不必要的。这样做的简单原因是 change tracking,它是由 Linq to Sql 和 Entity Framework 实现的。您需要做的就是:

    • 实例化 ERPDataContext 并使其保持活动状态

    • 获取要更改的行并为其分配新值

    • 致电SubmitChanges()

    然后,ORM 将更新数据库中的原始行,因为它 keeps track 实体中的原始值和新值。

    示例(所有代码都内联):

    using (var context = new ERPDataContext())
    {
        var STD = context.STUDENTs.SingleOrDefault(obj=>obj.ID==idToLookup);
    
        if (STD != null)
        {
             STD.SomeValue = someValue;
        }
    
        context.SubmitChanges(); // submit *CHANGES*
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-15
      • 2017-05-08
      • 1970-01-01
      • 2012-03-10
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多