В Entity Framework невозможно вставить данные в базу данных, потому что столбец IsDeleted равен null, хотя он установлен в false.

Вопрос или проблема

Как я могу исправить это исключение?

InnerException = {"Не удалось вставить значение NULL в столбец 'IsDeleted', таблица 'snapshot2_new.dbo.Workflows'; столбец не допускает NULL. Вставка не удалась.\r\nОперация была прервана."}

Это происходит в этом методе:

public async Task<Workflow> CopyWorkflow(int id, int userId)
{

        var wf = await this._context.Workflows
                    .Include(w => w.WorkflowStages)
                        .ThenInclude(s => s.Questions)
                    .Include(w => w.WorkflowStages)
                        .ThenInclude(s => s.StageTimeLimits)
                    .Include(w => w.WorkflowStages)
                        .ThenInclude(s => s.RequiredDocumentation)
                    .Include(w => w.WorkflowStages)
                        .ThenInclude(s => s.DocumentCategories)
                    .Include(w => w.WorkflowStages)
                        .ThenInclude(s => s.RolesCanUpdateStage)
                    .AsNoTracking()  // Обеспечивает, что нет отслеживания, чтобы предотвратить проблемы с оригинальной сущностью
                    .AsSplitQuery()
                    .FirstOrDefaultAsync(w => w.Id == id);

        if (wf == null)
        {
            throw new Exception("Рабочий процесс не найден.");
        }

        // Сбросить столбец идентификатора и другие свойства
        wf.Id = 0;  // Сбросить Id, чтобы база данных могла назначить новый
        wf.IsRetired = false;
        wf.IsDeleted = false;
        wf.DateCreated = DateTime.Now;
        wf.DateUpdated = DateTime.Now;


        // Добавить изменённый рабочий процесс в контекст
        _context.Workflows.Add(wf);
        await _context.SaveChangesAsync(); // Использовать асинхронное сохранение

        return wf;
}

Я остановился с отладчиком перед сохранением и у wf значение false для IsDeleted:
это запрос, сгенерированный Entity Framework

[23:44:36 ERR] Не удалось выполнить DbCommand (20ms) [Parameters=[@p0='?' (DbType = DateTime2), @p1='?' (DbType = DateTime2), @p2='?' (DbType = Boolean), @p3='?' (DbType = Boolean), @p4='?' (DbType = Boolean), @p5='?' (DbType = Boolean), @p6='?' (DbType = Int32), @p7='?' (DbType = Int32), @p8='?' (Size = 4000), @p9='?' (DbType = Int32)], CommandType="Text", CommandTimeout="30"]
SET NOCOUNT ON;
INSERT INTO [Workflows] ([DateCreated], [DateUpdated], [IsEnabledDocumentTemplates], [IsQVAccountsProductionRequired], [IsRetired], [IsTemplate], [ManagingAgentId], [UserId], [WorkflowTitle], [WorkflowTypeId])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9);
SELECT [WorkflowId], [IsDeleted]
FROM [Workflows]
WHERE @@ROWCOUNT = 1 AND [WorkflowId] = scope_identity();

Ответ или решение

Чтобы решить проблему с ошибкой вставки в базу данных, вызванной тем, что столбец IsDeleted не может быть равен NULL, вам нужно убедиться, что вы правильно присваиваете значение для этого столбца перед добавлением нового объекта в контекст Entity Framework.

В вашем коде вы уже присваиваете значение false для wf.IsDeleted, однако причина ошибки может заключаться в том, что Entity Framework не отслеживает данный объект как изменяемый, потому что вы используете метод AsNoTracking(). Это может привести к тому, что изменения, которые вы сделали в объекте wf, не будут распознаны при сохранении в базе данных.

Вот как вы можете исправить проблему:

  1. Уберите метод AsNoTracking() из вашего запроса, чтобы Entity Framework мог отслеживать изменения объектов после их извлечения из базы данных.

  2. Если вы по каким-то причинам хотите оставить AsNoTracking(), вам нужно создать новый объект, который будет копией wf, и установить значения свойств, включая IsDeleted.

Окончательная версия вашего метода CopyWorkflow может выглядеть следующим образом:

public async Task<Workflow> CopyWorkflow(int id, int userId)
{
    var wf = await this._context.Workflows
                .Include(w => w.WorkflowStages)
                    .ThenInclude(s => s.Questions)
                .Include(w => w.WorkflowStages)
                    .ThenInclude(s => s.StageTimeLimits)
                .Include(w => w.WorkflowStages)
                    .ThenInclude(s => s.RequiredDocumentation)
                .Include(w => w.WorkflowStages)
                    .ThenInclude(s => s.DocumentCategories)
                .Include(w => w.WorkflowStages)
                    .ThenInclude(s => s.RolesCanUpdateStage)
                .FirstOrDefaultAsync(w => w.Id == id);

    if (wf == null)
    {
        throw new Exception("Workflow not found.");
    }

    // Создание нового экземпляра Workflow и копирование значений
    var newWorkflow = new Workflow()
    {
        Id = 0,  // Сброс идентификатора для автогенерации в БД
        IsRetired = false,
        IsDeleted = false, // Убедитесь, что вы устанавливаете IsDeleted
        DateCreated = DateTime.Now,
        DateUpdated = DateTime.Now,
        // Копируйте другие свойства из wf, если это необходимо
        // Например, если у Workflow есть другие свойства, их также нужно задать здесь
        // WorkflowStages = wf.WorkflowStages.Select(stage => new WorkflowStage
        // {
        //     // Укажите необходимые свойства
        // }).ToList()
    };

    // Добавьте новый Workflow в контекст
    _context.Workflows.Add(newWorkflow);
    await _context.SaveChangesAsync(); // Асинхронное сохранение

    return newWorkflow;
}

Таким образом, вы создаете новый объект newWorkflow, который будет правильно добавлен в базу данных с заданным значением поля IsDeleted, и это должно устранить проблему с ошибкой вставки. Не забудьте также копировать другие необходимые свойства, если они требовательны в вашей логике.

Оцените материал
Добавить комментарий

Капча загружается...