I'm having issues updating entities when referencing the same table multiple times in the one entity.
I have two Classes User
and Expense
. Expense
is referencing to the User
multiple times:
User
- Who lodged the ExpenseApprovedUser
- Who approvedProcessedUser
- Who processedModifiedUser
- Who modified the Expense
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; }
}
When i update the field ModifiedByUserId
i get this:
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.
However if i null the ModifiedByUserId
it updates as normal.
I have also tried to null the ModifiedBy
and set the ModifiedByUserId
with the same result.
I've looked at multiple SO posts and spent 12 hours trying to figure out what seems like something that should be so simple but i and can't find anything that's worked.
(I'd prefer to stay away from fluent api if possible.)
Example
Bob and Jim are in the User
table and then there's a Expense
Bod originally Modified the Expense
so ModifiedByUserId
is set to Bob's User.Id
. I've now edited the Expense
so the ModifiedByUserId
should now be my User.Id
. Nothing changes in the User
, just the Expense
Generated 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]);
Code
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;
}
Update Expense:
public async Task<Expense> Update(Expense expense)
{
Expenses.Update(expense);
await Context.SaveAsync();
return expense;
}
Repository Update
public void Update(TEntity entity)
{
_dbSet.Attach(entity);
_context.SetState(entity, EntityState.Modified);
}