EF Core无法为表中的身份列插入显式值

时间:2020-04-16 19:27:18

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

我见过this questionthisthis,但是以下错误并未消失:

当IDENTITY_INSERT设置为OFF时,无法为表“产品”中的标识列插入显式值。

我尝试过的是:

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
public int Id { get; set; }

此外,我尝试将其设置为None

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }

T-SQL代码如下:

CREATE TABLE Orders
(
    Id INT IDENTITY(1,1),
    DatePlaced datetime NOT NULL,   
    CONSTRAINT PK_Order_Id PRIMARY KEY (Id)
)

CREATE TABLE OrderItems
(
    Id INT IDENTITY(1,1),
    IdOrder INT NOT NULL
        CONSTRAINT FK_OrderItems_IdOrder__Orders_Id FOREIGN KEY(IdOrder) REFERENCES Orders(Id),
    IdProduct INT NOT NULL
        CONSTRAINT FK_OrderItems_IdProduct__Products_Id FOREIGN KEY(IdProduct) REFERENCES Products(Id),
    Quantity INT NOT NULL,
    TotalPrice decimal (18,2),  
    CONSTRAINT PK_OrderItem_Id PRIMARY KEY (Id)
)

CREATE TABLE Products
(
    Id INT IDENTITY(1,1),
    Name varchar(100), 
    CONSTRAINT PK_Product_Id PRIMARY KEY (Id)
)

模型类如下:

public partial class Order
{
    public Order()
    {
        OrderItems = new HashSet<OrderItem>();
    }

    public int Id { get; set; }

    public DateTime DatePlaced { get; set; }

    public virtual ICollection<OrderItem> OrderItems { get; set; }
}

public partial class OrderItem
{
    public int Id { get; set; }

    public int Quantity { get; set; }

    [Column(TypeName = "decimal(18,2)")]
    public decimal? TotalPrice { get; set; }

    public virtual Order Order { get; set; }
    public virtual Product Product { get; set; }
}

public partial class Product
{
    public Product() { }

    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }       

    public string Name { get; set; }
}

Customer模型:

public class Customer : IdentityUser
{        
    public string FirstName { get; set; }

    public string LastName { get; set; }
    public virtual ICollection<Order> Orders { get; set; }
}

我想要保存OrderOrderItems。保存代码如下:

public async Task Add(Order order)
{
    order.Customer = _context.Customers.Find(order.Customer.Id);    
    await _context.AddAsync(order);
    await _context.SaveChangesAsync();
}

OrderService类:

    public async Task<OrderDto> Add(OrderDto orderDto)
    {
        var order = _mapper.Map<Order>(orderDto);
        await _orderRepository.Add(order);        
        orderDto.Id = order.Id;
        return orderDto;

    }

请告诉我我做错了什么?请不要关闭我的问题,因为它不是重复的。

2 个答案:

答案 0 :(得分:0)

此行为的原因是Automapper创建了一个新实例,并且实体框架认为POCO都是应该插入的所有新实体。

因此解决方案是将Attach现有实体添加到`DbContext。 It is described in great tutorial here

所以解决方案如下:

public async Task Add(Order order)
{            
    _context.Attach(order.Customer);
    foreach (var orderItem in order.OrderItems)
    {
        _context.Attach(orderItem.Product);
    }            
    await _context.Orders.AddAsync(order);
}

整个代码看起来像这样。

服务层:

public async Task<OrderDto> Add(OrderDto orderDto)
{
    var order = _mapper.Map<Order>(orderDto);
    await _orderRepository.Add(order);        
    orderDto.Id = order.Id;
    return orderDto;
}

存储层:

public async Task Add(Order order)
{            
    _context.Attach(order.Customer);
    foreach (var orderItem in order.OrderItems)
    {
        _context.Attach(orderItem.Product);
    }            
    await _context.Orders.AddAsync(order);
}

答案 1 :(得分:0)

另一种解决方案是使用_mapper.Map(sourceProperty, destinationProperty);。这不会更改参考。但是,在设置配置时,请确保忽略您不想映射的属性(即主键)。

例如在映射配置文件类的构造函数下:

CreateMap<SourceType, DestinationType>()
.ForMember(destination => destination.PK, options => options.Ignore());
相关问题