EF Core Невозможно вставить явное значение для столбца идентификаторов в таблице - PullRequest
1 голос
/ 16 апреля 2020

Я видел этот вопрос , это и это , однако следующая ошибка не исчезла:

Невозможно вставьте явное значение для столбца идентификаторов в таблице «Продукты», если для параметра 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; }
}

Я хочу сохранить Order и OrderItems. Код сохранения выглядит так:

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 голосов
/ 22 апреля 2020

Другое решение будет использовать _mapper.Map(sourceProperty, destinationProperty);. Это не меняет ссылку. Однако при настройке конфигурации обязательно игнорируйте свойство, которое вы не хотите отображать (например, первичный ключ).

например, под конструктором класса профиля отображения:

CreateMap<SourceType, DestinationType>()
.ForMember(destination => destination.PK, options => options.Ignore());
0 голосов
/ 17 апреля 2020

Причина такого поведения заключается в том, что Automapper создает новый экземпляр, и Entity Framework считает, что POCO - это все новые сущности, которые должны быть вставлены.

Таким образом, решение состоит в том, чтобы Attach существующих сущностей « DbContext. Это описано в большом руководстве здесь .

Итак, решение выглядит так:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...