【问题标题】:Parent - Child relation Child ID父子关系子ID
【发布时间】:2020-06-03 14:27:36
【问题描述】:

我有以下课程

public class Order
{
    public int OrderID {get;set;}
    /*...
    Some other properties
    ...*/
    public ICollection<OrderDetail> Details {get;set;}
}

public class OrderDetail
{
    public int OrderID {get;set;}
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OrderDetailID {get;set;}
    /*...
    Some other properties
    ...*/

    public Order Order {get;set;}
}

我还在 OnModelCreation 中指定了如下关系:

modelBuilder.Entity<OrderDetail>().HasKey(detail => new { detail.OrderID, detail.OrderDetailID});
modelBuilder.Entity<OrderDetail>().HasOne(detail => detail.Order)
                                            .WithMany(order => order.Details)
                                            .HasForeignKey(detail => detail.OrderID).OnDelete(DeleteBehavior.Cascade);

一切正常,没有任何错误。
我的问题是,在这种情况下,当我创建一个包含详细信息的订单时,OrderDetailID 会针对所有详细信息递增,并且我在数据库中得到以下信息。

OrderID OrderDetailID .... 17 19 3 15.0000 15.0000 EA 17 20 3 15.0000 15.0000 EA 18 21 1 25.0000 0.0000 EA 18 22 1 25.0000 0.0000 EA

我了解 OrderDetailID 的工作方式与我的代码中的配置相对应。但是我的问题是我需要在数据库中获取如下图片:

OrderID OrderDetailID .... 17 1 3 15.0000 15.0000 EA 17 2 3 15.0000 15.0000 EA 18 1 1 25.0000 0.0000 EA 18 2 1 25.0000 0.0000 EA

换句话说,我需要将每个新订单的 OrderDetailID 重置为 1。
我在 Entity Framework 中找不到任何配置选项来让它以我需要的方式工作。

提前谢谢你。

【问题讨论】:

  • 您可以在数据库中创建一个触发器,它应该在插入时增加它
  • @DavidEdel 触发器应该如何确定是增加值还是重置为 1?
  • 见下方答案

标签: c# asp.net-core entity-framework-core


【解决方案1】:

您所期望的称为基于另一列的身份列。 SQL Server 和 EF Core 都没有对此的默认支持。

您必须手动完成。在 EF Core 中,您必须通过从数据库中获取此属性(列)的最大值然后将其递增 1 来分配属性(列)值。

【讨论】:

    【解决方案2】:

    我想没有像 autoIncrementing Id 这样可以重置的东西,它看起来更像是您应该在代码中创建的行为,也许可以考虑使用 Details 列表中的索引作为您的 OrderDetailID

    【讨论】:

      【解决方案3】:

      最好是在插入时在数据库中创建触发器

      它应该根据该特定订单的最高 ID 设置 orderDetailId

      例子:

      SELECT ISNULL(MAX(OrderDetailID)+1,1) FROM orderDetails WHERE orderID = inserted.OrderID

      【讨论】:

        【解决方案4】:

        经过长时间的审查,我最终将以下脚本添加到迁移中。

        migrationBuilder.Sql(@"CREATE OR ALTER TRIGGER [DetailLineNbr] ON Details AFTER INSERT AS 
                                BEGIN
                                declare @minLineNbr int;
                                declare @maxExistingLineNbr int;
                                SET @minLineNbr = (SELECT MIN(DetailID) FROM inserted);
                                SET @maxExistingLineNbr = ISNULL((SELECT MAX(LineNbr) FROM Details WHERE Details.OrderID in (select inserted.OrderID from inserted) AND Details.DetailID not in (select inserted.DetailID from inserted)),0);
                                UPDATE Details
                                SET LineNbr = Details.DetailID - @minLineNbr + @maxExistingLineNbr + 1
                                WHERE Details.OrderID in (select inserted.OrderID from inserted) AND Details.DetailID in (select inserted.DetailID from inserted) 
                                END");
        

        David Edel 建议的解决方案仅适用于单行插入。 不幸的是,在我的例子中,几乎所有的插入都是多行插入的。

        【讨论】:

          猜你喜欢
          • 2020-11-25
          • 2015-10-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多