【问题标题】:Using Entity Framework Code First approach, how do I create an entity that has a list of related entities as a child property?使用实体框架代码优先方法,如何创建一个具有相关实体列表作为子属性的实体?
【发布时间】:2015-08-01 06:33:49
【问题描述】:

已解决!!!

感谢下面 Gert 制作的 cmets,我得以解决。在保存订单之前,我只需要将 Product 实体附加到与 Order 实体相同的上下文中:

public int Create(Order entity)
        {
            var order = entity;

            foreach (var product in order.Products)
            {
                db.Products.Attach(product);
            }

            db.Orders.Add(order);
            db.SaveChanges();

            return order.Id;
        }

原帖

感谢收看。这是我的用例:

在电子商务应用程序中,我需要创建一个Order。 Order 具有一个或多个 Product 实体作为其属性之一。这是我的两个域模型:

订单

 [Table("Order")]
    public class Order
    {
        [Required(ErrorMessage = "Please enter a description.")]
        public string Description { get; set; }

        [Required(ErrorMessage = "Please enter a trackingnumber.")]
        public string TrackingNumber { get; set; }

        [Key]
        public int Id { get; set; }

        [Required(ErrorMessage = "Please enter an isactive.")]
        public bool IsActive { get; set; }

        public int UserId { get; set; }

        public virtual User User { get; set; }

        public int OrderStatusTypeId { get; set; }

        public virtual OrderStatusType OrderStatusType { get; set; }

        private ICollection<Product> _products;
        public virtual ICollection<Product> Products
        {
            get { return _products ?? (_products = new Collection<Product>()); }
            set { _products = value; }
        }
    }

产品

[Table("Product")]
    public class Product
    {
        [Required(ErrorMessage = "Please enter a description.")]
        public string Description { get; set; }

        [Key]
        public int Id { get; set; }
        [Required(ErrorMessage = "Please enter a name.")]
        public string Name { get; set; }


        private ICollection<Order> _orders;
        public virtual ICollection<Order> Orders
        {
            get { return _orders ?? (_orders = new Collection<Order>()); }
            set { _orders = value; }
        }

        private ICollection<DeviceModel> _devicemodels;
        public virtual ICollection<DeviceModel> DeviceModels
        {
            get { return _devicemodels ?? (_devicemodels = new Collection<DeviceModel>()); }
            set { _devicemodels = value; }
        }
    }

以下是用户创建的帖子对象:

{
  "Description": "Test description",
  "TrackingNumber": "12345",
  "Id": 1,
  "IsActive": true,
  "UserId": 0,
  "User": {
    "Email": "john@gmail.com",
    "FirstName": "John",
    "Id": 1,
    "LastName": "Doe"
  },
  "OrderStatusTypeId": 0,
  "OrderStatusType": {
    "Description": "The order is in processing.",
    "Id": 1,
    "Title": "Processing"
  },
  "Products": [{"Description":"Test product","Id":1,"Name":"Product A","DeviceModels":[]},{"Description":"Test","Id":2,"Name":"Product B","DeviceModels":[]}]
}

预期行为

当我将POST 这个Order 对象发送到服务器时,我预计会创建一个新订单,并且会简单地引用属于该订单的产品。

遇到的行为

每次我下订单时,相关产品都会在产品表中添加一个新产品。因此,我没有几个产品被多个订单引用,而是几个产品与订单具有一对一的关系。

这是我的 Products 表最终的样子(注意重复的产品):

更新

代码优先方法确实为我创建了一个ProductOrders 连接表,它甚至将订单和产品ID 添加到该表中:

那么为什么它还将产品作为新实体添加到Product 表中,而不是简单地引用我传递给它的键?

提前致谢。

更新 #1:

这是我用于创建订单的存储库类:

  public class OrderRepository : IRepository<Order, int>
    {
        private readonly ApplicationDbContext db;

        public OrderRepository(ApplicationDbContext dbContext)
        {
            db = dbContext;
        }

        /// <summary>
        ///     Creates and saves a new 'Order' entity.
        /// </summary>
        /// <param name="entity">The Order to save.</param>
        /// <returns>The id (int) of the newly created Order.</returns>
        public int Create(Order entity)
        {
            var order = entity;
            db.Orders.Add(order);
            db.SaveChanges();

            return order.Id;
        }

        }
    }

【问题讨论】:

  • 这个问题与实体框架本身一样古老。在添加订单之前附加产品。
  • 谢谢格特,但这就是我迷路的地方。您能否提供一些代码来帮助我对此有所了解?例如,我是否创建一个新产品对象,然后将其附加到新订单,然后提交到数据库?非常感谢您的帮助。
  • 格特!!非常感谢——你让我度过了一个周末。有用!我会为其他人发布决议。干杯!

标签: c# entity-framework ef-code-first


【解决方案1】:

您需要为您的集合定义映射。这是一个使用流畅映射接口的示例。

public class OrderMapping:  EntityTypeConfiguration<Order>
{
       public OrderMapping()
      {
         HasMany(o => o.Products).WithMany(p => p.Orders).Map(m =>
            {
                m.MapLeftKey("OrderId");
                m.MapRightKey("ProductId");
                m.ToTable("Order_Products");
            });
      }          
}

这将在订单和产品之间创建一个链接表。

【讨论】:

  • 谢谢,但即使有了这个额外的逻辑,其他产品仍会继续添加到产品表中。
  • @MatthewPatrickCashatt,在 SaveChanges() 方法之前,您的应用程序代码是什么样的?实体是如何创建的?您是否将产品附加到上下文中,然后将它们与订单相关联?
  • 感谢 DDiVita——我在上面的 Order Repo 类中添加了一个 sn-p。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-05
  • 1970-01-01
相关资源
最近更新 更多