使用linq和实体框架更新复杂对象
我有一个对象,叫做Order,它有几个属性,这些属性也是对象。当我更新Order对象时,简单的属性被正确地更新,但是复杂的属性(位于不同的表中)没有被更新,而是创建了新的属性。我做错了什么。此外,当我尝试获取多个项目属性(本例中为项目)时,它返回null,而不是保存的项目 代码示例:使用linq和实体框架更新复杂对象,linq,entity-framework-4.1,Linq,Entity Framework 4.1,我有一个对象,叫做Order,它有几个属性,这些属性也是对象。当我更新Order对象时,简单的属性被正确地更新,但是复杂的属性(位于不同的表中)没有被更新,而是创建了新的属性。我做错了什么。此外,当我尝试获取多个项目属性(本例中为项目)时,它返回null,而不是保存的项目 代码示例: [DataContract] public class Order { [Key] [DataMember] public int Id { get; set; } #region
[DataContract]
public class Order
{
[Key]
[DataMember]
public int Id { get; set; }
#region Order Details
[DataMember]
public int? ReferenceNumber { get; set; }
[DataMember]
public virtual Status CurrentStatus { get; set; }
[DataMember]
public DateTime? CurrentStatusUpdatedOn { get; set; }
[DataMember]
[MaxLength(1024)] public string ArchiveFileName { get; set; }
[DataMember]
public double TotalPrice { get; set; }
[DataMember]
public bool DigitallySigned { get; set; }
[DataMember]
public int DigitalSigningReferenceId { get; set; }
[DataMember]
public virtual Priority Priority { get; set; }
[DataMember]
public virtual ICollection<Item> Items { get; set; }
.....
}
[DataContract]
public class Item : IItem
{
[DataMember]
[Key]
public int Id { get; set; }
[DataMember]
public virtual Order ParentOrder { get; set; }
[DataMember]
public virtual ItemType Type { get; set; }
[DataMember]
public string ItemReference { get; set; }
[DataMember]
public int FeeReference { get; set; }
[DataMember]
public int Quantity { get; set; }
[DataMember]
public decimal Price { get; set; }
[DataMember]
public string Name { get; set; }
....
}
private static bool UpdateOrderDetails(Order order, DatabaseContext context)
{
var savedOrder =
context.Orders.Include("Priority").Include("CurrentStatus").Where(o => o.Id == order.Id).FirstOrDefault();
//context.Orders.SingleOrDefault(o => o.Id == order.Id);
if (savedOrder != null)
{
savedOrder.Priority = order.Priority;
savedOrder.ReferenceNumber = order.ReferenceNumber;
savedOrder.ShohamId = order.ShohamId;
savedOrder.TotalPrice = order.TotalPrice;
savedOrder.UpdatedOn = DateTime.Now;
savedOrder.CreatedOn = order.CreatedOn;
savedOrder.ArchiveFileName = order.ArchiveFileName;
savedOrder.ClientEmail = order.ClientEmail;
savedOrder.ClientFirstName = order.ClientFirstName;
savedOrder.ClientIdentificationNumber = order.ClientIdentificationNumber;
savedOrder.ClientIdentificationType = order.ClientIdentificationType;
savedOrder.ClientLastName = order.ClientLastName;
savedOrder.ClientPrimaryPhone = order.ClientPrimaryPhone;
savedOrder.ClientSecondaryPhone = order.ClientSecondaryPhone;
savedOrder.CurrentStatus = order.CurrentStatus;
savedOrder.CurrentStatusUpdatedOn = order.CurrentStatusUpdatedOn;
savedOrder.DigitallySigned = order.DigitallySigned;
savedOrder.DigitalSigningReferenceId = order.DigitalSigningReferenceId;
if (order.Items != null)
{
foreach (var item in order.Items)
{
var savedItem = savedOrder.Items.Single(x => x.ItemReference == item.ItemReference);
if (savedItem != null)
{
savedItem.Price = item.Price;
savedItem.Quantity = item.Quantity;
}
}
}
context.Entry(savedOrder).State = EntityState.Modified;
var i = context.SaveChanges();
[DataContract]
公共阶级秩序
{
[关键]
[数据成员]
公共int Id{get;set;}
#地区订单详情
[数据成员]
公共int?引用编号{get;set;}
[数据成员]
公共虚拟状态CurrentStatus{get;set;}
[数据成员]
公共日期时间?CurrentStatusUpdateOn{get;set;}
[数据成员]
[MaxLength(1024)]公共字符串ArchiveFileName{get;set;}
[数据成员]
公共双总价{get;set;}
[数据成员]
公共布尔数字签名{get;set;}
[数据成员]
public int DigitalSigningReferenceId{get;set;}
[数据成员]
公共虚拟优先级{get;set;}
[数据成员]
公共虚拟ICollection项{get;set;}
.....
}
[数据合同]
公共类项目:IItem
{
[数据成员]
[关键]
公共int Id{get;set;}
[数据成员]
公共虚拟顺序ParentOrder{get;set;}
[数据成员]
公共虚拟ItemType类型{get;set;}
[数据成员]
公共字符串ItemReference{get;set;}
[数据成员]
公共int引用{get;set;}
[数据成员]
公共整数数量{get;set;}
[数据成员]
公共十进制价格{get;set;}
[数据成员]
公共字符串名称{get;set;}
....
}
私有静态bool UpdateOrderDetails(订单、数据库上下文)
{
var savedOrder=
context.Orders.Include(“优先级”).Include(“当前状态”).Where(o=>o.Id==order.Id).FirstOrDefault();
//context.Orders.SingleOrDefault(o=>o.Id==order.Id);
if(savedOrder!=null)
{
savedOrder.Priority=order.Priority;
savedOrder.ReferenceNumber=order.ReferenceNumber;
savedOrder.ShohamId=order.ShohamId;
savedOrder.TotalPrice=order.TotalPrice;
savedOrder.UpdatedOn=DateTime.Now;
savedOrder.CreatedOn=order.CreatedOn;
savedOrder.ArchiveFileName=order.ArchiveFileName;
savedOrder.ClientEmail=order.ClientEmail;
savedOrder.ClientFirstName=order.ClientFirstName;
savedOrder.ClientIdentificationNumber=order.ClientIdentificationNumber;
savedOrder.ClientIdentificationType=order.ClientIdentificationType;
savedOrder.ClientLastName=order.ClientLastName;
savedOrder.ClientPrimaryPhone=order.ClientPrimaryPhone;
savedOrder.ClientSecondaryPhone=order.ClientSecondaryPhone;
savedOrder.CurrentStatus=order.CurrentStatus;
savedOrder.CurrentStatusUpdatedOn=order.CurrentStatusUpdatedOn;
savedOrder.DigitallySigned=order.DigitallySigned;
savedOrder.DigitalSigningReferenceId=order.DigitalSigningReferenceId;
if(order.Items!=null)
{
foreach(order.Items中的变量项)
{
var savedItem=savedOrder.Items.Single(x=>x.ItemReference==item.ItemReference);
if(savedItem!=null)
{
savedItem.Price=项目价格;
savedItem.Quantity=物料.Quantity;
}
}
}
context.Entry(savedOrder).State=EntityState.Modified;
var i=context.SaveChanges();
如果您不想为导航属性插入新对象,则必须在分配值之前将其附加到上下文中。对于项目集合问题,您需要在查询时包含集合。不需要包含其他两个导航属性,并将状态设置为已修改在您的示例中都不是。对于Include
,您可以在EF 4.1中使用具有lambda表达式的强类型版本:
private static bool UpdateOrderDetails(Order order, DatabaseContext context)
{
var savedOrder = context.Orders.Include(o => o.Items)
.Where(o => o.Id == order.Id)
.FirstOrDefault();
if (savedOrder != null)
{
context.Priorities.Attach(order.Priority);
context.CurrentStati.Attach(order.CurrentStatus);
savedOrder.Priority = order.Priority;
// etc.
var i = context.SaveChanges();
}
}
order
和savedOrder
是否从同一上下文中创建?是否将order
对象从上下文中分离?谢谢@Slauma,我正在尝试您的方法,我收到以下错误:指定的包含路径无效。EntityType“Moj.FE.Data.order”未声明名为“Items”的导航属性。@Etchin:Strange.Items
是什么?您在代码中使用的是order.Items
。您能否显示order
类在您的模型中是如何定义的?(您可以编辑问题以显示该类。)@艾金:非常奇怪。这应该真的能用。你有流畅的API代码吗?你的上下文类是什么样子的?什么是IItem
?你的数据库中的Items表是否有顺序的外键,比如ParentOrder\u Id
或order\u Id
?@Slauma:你尝试过使用System.Data.Entity;t添加吗o包含UpdateOrderDetails()方法的类?这修复了我遇到的一个类似问题,其中Include()方法不会采用lambda表达式(ie仅适用于包含导航属性名称的字符串。@HOCA:我想,这不是原因。这是一个运行时错误。如果使用System.Data.Entity
将丢失,我们将在编译时出错。