C # EF CF - Нарушение ограничения ссылочной целостности: умножение внешних ключей на одну таблицу - PullRequest
0 голосов
/ 23 июня 2019

У меня проблемы с обновлением сущностей при многократном обращении к одной и той же таблице в одной сущности.

У меня есть два класса User и Expense.Expense ссылается на User несколько раз:

  • User - Кто подал расходы
  • ApprovedUser - Кто утвердил
  • ProcessedUser - Кто обработал
  • ModifiedUser - Кто изменил Расход
    public class User
    {
        /// <summary>
        /// User Id
        /// </summary>
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Key]
        public string Id { get; set; }

        /// <summary>
        /// Display Name
        /// </summary>
        [Required]
        [Display(Name = "Display Name")]
        public string DisplayName { get; set; }
    }

    public class Expense
    {
        /// <summary>
        /// User Id
        /// </summary>
        [Required]
        [Display(Name = "User Id")]
        public string UserId { get; set; }

        /// <summary>
        /// Linked User
        /// </summary>
        [ForeignKey("UserId")]
        public User User { get; set; }

        /// <summary>
        /// Approved User Id
        /// </summary>
        [Display(Name = "Approved User Id")]
        public string ApprovedUserId { get; set; } = null;

        /// <summary>
        /// Linked Approve User
        /// </summary>
        [ForeignKey("ApprovedUserId")]
        public User ApprovedUser { get; set; }

        /// <summary>
        /// Processed User Id
        /// </summary>
        [Display(Name = "Processed User Id")]
        public string ProcessedUserId { get; set; } = null;

        /// <summary>
        /// Linked Processed User
        /// </summary>
        [ForeignKey("ProcessedUserId")]
        public User ProcessedUser { get; set; }

        /// <summary>
        /// Modified User Id
        /// </summary>
        [Display(Name = "Modified By User Id")]
        public string ModifiedByUserId { get; set; }

        /// <summary>
        /// Linked Modified User
        /// </summary>
        [ForeignKey("ModifiedByUserId")]
        public User ModifiedBy { get; set; }
    }

Когда я обновляю поле ModifiedByUserId, я получаю это: A referential integrity constraint violation occurred: The property value(s) of 'User.Id' on one end of a relationship do not match the property value(s) of 'Expense.ModifiedByUserId' on the other end.

Однако, если я обнуляю ModifiedByUserId, он обновляется как обычно.Я также пытался обнулить ModifiedBy и установить ModifiedByUserId с тем же результатом.

Я просмотрел несколько сообщений SO и потратил 12 часов, пытаясь выяснить, что, по-видимому, должно бытьтак просто, но я не могу найти ничего, что сработало.

(я бы предпочел держаться подальше от беглого API, если это возможно.)

Пример

Боб и Джим находятся в таблице User, а затем есть Expense Бод, изначально модифицированный Expense, поэтому ModifiedByUserId установлен на Боба User.Id.Я сейчас отредактировал Expense, поэтому ModifiedByUserId теперь должен быть моим User.Id.Ничего не меняется в User, только Expense

Сгенерированный SQL

create table [dbo].[Expense] (
    [Id] [int] not null identity,
    [SubmittedDate] [datetime2](7) not null,
    [UserId] [nvarchar](128) not null,
    [ApprovedUserId] [nvarchar](128) null,
    [ProcessedUserId] [nvarchar](128) null,
    [State] [int] not null,
    [ModifiedByUserId] [nvarchar](128) null,
    [LastNotification] [datetime2](7) not null,
    [NextNotification] [datetime2](7) not null,
    [NumberOfNotifications] [int] not null,
    [StopNotifications] [bit] not null,
    [Inserted] [datetime2](7) not null,
    [Updated] [datetime2](7) not null,
    [Deleted] [bit] not null,
    primary key ([Id])
);

create table [dbo].[User] (
    [Id] [nvarchar](128) not null,
    [DisplayName] [nvarchar](max) not null,
    [Department] [nvarchar](max) null,
    [JobTitle] [nvarchar](max) null,
    [Email] [nvarchar](max) not null,
    [TelephoneNumber] [nvarchar](max) null,
    [MobileNumber] [nvarchar](max) null,
    [DownloadedProfileImg] [bit] not null,
    [ManagerId] [nvarchar](128) null,
    [Deleted] [bit] not null,
    primary key ([Id])
);

alter table [dbo].[Expense] add constraint [Expense_ApprovedUser] foreign key ([ApprovedUserId]) references [dbo].[User]([Id]);
alter table [dbo].[Expense] add constraint [Expense_ModifiedBy] foreign key ([ModifiedByUserId]) references [dbo].[User]([Id]);
alter table [dbo].[Expense] add constraint [Expense_ProcessedUser] foreign key ([ProcessedUserId]) references [dbo].[User]([Id]);
alter table [dbo].[Expense] add constraint [Expense_User] foreign key ([UserId]) references [dbo].[User]([Id]);
alter table [dbo].[User] add constraint [User_Manager] foreign key ([ManagerId]) references [dbo].[User]([Id]);

Код

var expense = await ExpenseService.GetExpense(4);
expense.Updated = DateTime.Now;
expense.ModifiedByUserId = "user_id_string";
await ExpenseService.Update(expense);

GetExpense

        public async Task<Expense> GetExpense(int? id)
        {
            var expense = await Expenses.Query()
                .Include(x => x.User)
                .Include(x => x.ModifiedBy)
                .Include(x => x.ApprovedUser)
                .Include(x => x.ProcessedUser)
                .FirstAsync(x => x.Id == id);

            return expense;
        }

Расходы на обновление:

        public async Task<Expense> Update(Expense expense)
        {
            Expenses.Update(expense);
            await Context.SaveAsync();

            return expense;
        }

Обновление репозитория

        public void Update(TEntity entity)
        {
            _dbSet.Attach(entity);
            _context.SetState(entity, EntityState.Modified);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...