Need a help to update the model












2















I have a model called ClubApplicationUser which is bridge between the Club and ApplicationUser which is extended model of Identity User model:



public class ClubApplicationUser
{
public Guid ClubID { get; set; }

public Club Club { get; set; }

public string Id { get; set; }

public ApplicationUser ApplicationUser { get; set; }

public DateTime DateCreated { get; set; }

public string CreatedBy { get; set; }

public DateTime LastDateModified { get; set; }

public string LastModifiedBy { get; set; }

public DateTime? DateDeleted { get; set; }

public string DeletedBy { get; set; }

public bool IsDeleted { get; set; }

[Timestamp]
public byte RowVersion { get; set; }

[ForeignKey("CreatedBy")]
public ApplicationUser ClubApplicationCreatedUser { get; set; }

[ForeignKey("LastModifiedBy")]
public ApplicationUser ClubApplicationLastModifiedUser { get; set; }



}


and in the ApplicationDBContext - OnModelCreating we defined the relationships:



builder.Entity<ClubApplicationUser>()
.HasKey(bc => new { bc.ClubID, bc.Id });

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.Club)
.WithMany(b => b.ClubApplicationUsers)
.HasForeignKey(bc => bc.ClubID);

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.ApplicationUser)
.WithMany(c => c.ClubApplicationUsers)
.HasForeignKey(bc => bc.Id);


We have an issue where we could NOT update this and we have the error:




InvalidOperationException: The property 'ClubID' on entity type
'ClubApplicationUser' is part of a key and so cannot be modified or
marked as modified. To change the principal of an existing entity with
an identifying foreign key first delete the dependent and invoke
'SaveChanges' then associate the dependent with the new principal.




Here's the AssignClub.cs:



public class AssignClubUserModel : ClubNamePageModel
{
private readonly AthlosifyWebArchery.Data.ApplicationDbContext _context;


public AssignClubUserModel(AthlosifyWebArchery.Data.ApplicationDbContext context)
{
_context = context;
}

public class AssignClubUserViewModel<ApplicationUser>
{

public string FirstName { get; set; }
public string LastName { get; set; }

public string UserName { get; set; }

public Guid SelectedClubID { get; set; }

public byte RowVersion { get; set; }

}

[BindProperty]
public AssignClubUserViewModel<ApplicationUser> AssignClubUser { get; set; }

public SelectList ClubNameSL { get; set; }

public async Task<IActionResult> OnGetAsync(Guid? id)
{



if (id == null)
return NotFound();

var user = await _context.Users
.Include(u => u.ClubApplicationUsers)
.Where(t => t.Id == id.ToString())
.Select(t => new AssignClubUserViewModel<ApplicationUser>
{
FirstName = t.FirstName,
LastName = t.LastName,
UserName = t.UserName,
SelectedClubID = t.ClubApplicationUsers.ElementAt(0).ClubID,
RowVersion = t.RowVersion
}).SingleAsync();


AssignClubUser = user;



// Use strongly typed data rather than ViewData.
ClubNameSL = new SelectList(_context.Club, "ClubID", "Name");

//PopulateClubsDropDownList(_context);

return Page();
}

public async Task<IActionResult> OnPostAsync(Guid id)
{
if (!ModelState.IsValid)
{
return Page();
}

// 1st approach:
// Modify the bridge model directly

var clubApplicationUserToUpdate = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());

if (clubApplicationUserToUpdate == null)
{
return await HandleDeletedUser();
}

_context.Entry(clubApplicationUserToUpdate)
.Property("RowVersion").OriginalValue = AssignClubUser.RowVersion;

_context.Entry(clubApplicationUserToUpdate)
.Property("ClubID").OriginalValue = AssignClubUser.SelectedClubID;

await _context.SaveChangesAsync();


// 2nd approach:
// Soft -Delete and Add
// Did the soft-deleting and managed to add a new one BUT then die the roll back (adding the old one)
// Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.
// Cannot insert duplicate key in object
// Due to duplicate key

/*var clubApplicatonUserToRemove = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());
ClubApplicationUser clubApplicatonUserToAdd = new ClubApplicationUser();
clubApplicatonUserToAdd.Id = id.ToString();
clubApplicatonUserToAdd.ClubID = AssignClubUser.SelectedClubID;


//_context.Entry(clubApplicatonUserToRemove)
// .Property("RowVersion").OriginalValue = User.RowVersion;

if (clubApplicatonUserToRemove != null)
{
_context.ClubApplicationUser.Remove(clubApplicatonUserToRemove);
await _context.SaveChangesAsync();
_context.ClubApplicationUser.Add(clubApplicatonUserToAdd);
await _context.SaveChangesAsync();
}*/




return Page();
}

private async Task<IActionResult> HandleDeletedUser()
{
//ClubA deletedClubApplicationUser = new ApplicationUser();
//ModelState.AddModelError(string.Empty,
// "Unable to save. The user was deleted by another user.");
//ClubNameSL = new SelectList(_context.Roles, "Id", "Name", User.UserRoles.ElementAt(0).RoleId);
return Page();
}

private async Task setDbErrorMessage(ApplicationUser dbValues,
ApplicationUser clientValues, ApplicationDbContext context)
{

if (dbValues.FirstName != clientValues.FirstName)
{
ModelState.AddModelError("User.FirstName",
$"Current value: {dbValues.FirstName}");
}

if (dbValues.LastName != clientValues.LastName)
{
ModelState.AddModelError("User.LastName",
$"Current value: {dbValues.LastName}");
}

if (dbValues.Email != clientValues.Email)
{
ModelState.AddModelError("User.Email",
$"Current value: {dbValues.Email}");
}



ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}

}


... and AssignClub.cshtml:



@page
@model AthlosifyWebArchery.Pages.Administrators.Users.AssignClubUserModel
@{
ViewData["Title"] = "Assign Club";
}
<h2>Assign Club</h2>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AssignClubUser.FirstName" class="control-label">
</label>
<input asp-for="AssignClubUser.FirstName" disabled class="form-
control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.LastName" class="control-label">
</label>
<input asp-for="AssignClubUser.LastName" disabled class="form-control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.UserName" class="control-label">
</label>
<input asp-for="AssignClubUser.UserName" disabled class="form-control" />
</div>
<div class="form-group">
<label class="control-label">Club</label>
<select asp-for="AssignClubUser.SelectedClubID" class="form-control"
asp-items="@Model.ClubNameSL">
<option value="">-- Select Club --</option>
</select>
<span asp-validation-for="AssignClubUser.SelectedClubID" class="text-danger"></span>
</div>

<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}


Environment:
.Net Core 2.2
Razor Pages



UPDATE - 1:



If we update this directly on the database by doing:



UPDATE [ClubApplicationUser]
SET ClubID = '85715C34-AFC6-4498-DA7F-08D66CAE7A01'
WHERE Id = 'ecbd27b4-03bc-4b99-82b3-76d9aa5bc7fc'


We could update this no problem. So it looks like it's contraint within the .Net core model.










share|improve this question

























  • To clarify why you can do it in the database versus not in EntityFramework. Entity Framework needs to identify an entity, it does this using the key, this is so it can keep track of various things such as changes - the SQL UPDATE statement needs the key properties in the WHERE clause. Hence the key properties make up the identity of the entity and if you change them its going to have problems. You could think about it as being a different entity and hence the create a new entity approach I suggested.

    – PhilS
    Jan 4 at 12:02











  • If you look at the EntityFrameworkCore source code in the SetPropertyModified method you can see it has explicit code blocking updates to keys and throwing InvalidOperationException

    – PhilS
    Jan 4 at 12:08













  • To my mind this is a symtom of the object-referential impedience mismatch as ClubApplicationUser is not an 'entity' - its not really responsible for its own lifecycle and should be part of the Club andor User if you were using a different more objectcentric persistence store.

    – PhilS
    Jan 4 at 12:17
















2















I have a model called ClubApplicationUser which is bridge between the Club and ApplicationUser which is extended model of Identity User model:



public class ClubApplicationUser
{
public Guid ClubID { get; set; }

public Club Club { get; set; }

public string Id { get; set; }

public ApplicationUser ApplicationUser { get; set; }

public DateTime DateCreated { get; set; }

public string CreatedBy { get; set; }

public DateTime LastDateModified { get; set; }

public string LastModifiedBy { get; set; }

public DateTime? DateDeleted { get; set; }

public string DeletedBy { get; set; }

public bool IsDeleted { get; set; }

[Timestamp]
public byte RowVersion { get; set; }

[ForeignKey("CreatedBy")]
public ApplicationUser ClubApplicationCreatedUser { get; set; }

[ForeignKey("LastModifiedBy")]
public ApplicationUser ClubApplicationLastModifiedUser { get; set; }



}


and in the ApplicationDBContext - OnModelCreating we defined the relationships:



builder.Entity<ClubApplicationUser>()
.HasKey(bc => new { bc.ClubID, bc.Id });

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.Club)
.WithMany(b => b.ClubApplicationUsers)
.HasForeignKey(bc => bc.ClubID);

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.ApplicationUser)
.WithMany(c => c.ClubApplicationUsers)
.HasForeignKey(bc => bc.Id);


We have an issue where we could NOT update this and we have the error:




InvalidOperationException: The property 'ClubID' on entity type
'ClubApplicationUser' is part of a key and so cannot be modified or
marked as modified. To change the principal of an existing entity with
an identifying foreign key first delete the dependent and invoke
'SaveChanges' then associate the dependent with the new principal.




Here's the AssignClub.cs:



public class AssignClubUserModel : ClubNamePageModel
{
private readonly AthlosifyWebArchery.Data.ApplicationDbContext _context;


public AssignClubUserModel(AthlosifyWebArchery.Data.ApplicationDbContext context)
{
_context = context;
}

public class AssignClubUserViewModel<ApplicationUser>
{

public string FirstName { get; set; }
public string LastName { get; set; }

public string UserName { get; set; }

public Guid SelectedClubID { get; set; }

public byte RowVersion { get; set; }

}

[BindProperty]
public AssignClubUserViewModel<ApplicationUser> AssignClubUser { get; set; }

public SelectList ClubNameSL { get; set; }

public async Task<IActionResult> OnGetAsync(Guid? id)
{



if (id == null)
return NotFound();

var user = await _context.Users
.Include(u => u.ClubApplicationUsers)
.Where(t => t.Id == id.ToString())
.Select(t => new AssignClubUserViewModel<ApplicationUser>
{
FirstName = t.FirstName,
LastName = t.LastName,
UserName = t.UserName,
SelectedClubID = t.ClubApplicationUsers.ElementAt(0).ClubID,
RowVersion = t.RowVersion
}).SingleAsync();


AssignClubUser = user;



// Use strongly typed data rather than ViewData.
ClubNameSL = new SelectList(_context.Club, "ClubID", "Name");

//PopulateClubsDropDownList(_context);

return Page();
}

public async Task<IActionResult> OnPostAsync(Guid id)
{
if (!ModelState.IsValid)
{
return Page();
}

// 1st approach:
// Modify the bridge model directly

var clubApplicationUserToUpdate = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());

if (clubApplicationUserToUpdate == null)
{
return await HandleDeletedUser();
}

_context.Entry(clubApplicationUserToUpdate)
.Property("RowVersion").OriginalValue = AssignClubUser.RowVersion;

_context.Entry(clubApplicationUserToUpdate)
.Property("ClubID").OriginalValue = AssignClubUser.SelectedClubID;

await _context.SaveChangesAsync();


// 2nd approach:
// Soft -Delete and Add
// Did the soft-deleting and managed to add a new one BUT then die the roll back (adding the old one)
// Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.
// Cannot insert duplicate key in object
// Due to duplicate key

/*var clubApplicatonUserToRemove = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());
ClubApplicationUser clubApplicatonUserToAdd = new ClubApplicationUser();
clubApplicatonUserToAdd.Id = id.ToString();
clubApplicatonUserToAdd.ClubID = AssignClubUser.SelectedClubID;


//_context.Entry(clubApplicatonUserToRemove)
// .Property("RowVersion").OriginalValue = User.RowVersion;

if (clubApplicatonUserToRemove != null)
{
_context.ClubApplicationUser.Remove(clubApplicatonUserToRemove);
await _context.SaveChangesAsync();
_context.ClubApplicationUser.Add(clubApplicatonUserToAdd);
await _context.SaveChangesAsync();
}*/




return Page();
}

private async Task<IActionResult> HandleDeletedUser()
{
//ClubA deletedClubApplicationUser = new ApplicationUser();
//ModelState.AddModelError(string.Empty,
// "Unable to save. The user was deleted by another user.");
//ClubNameSL = new SelectList(_context.Roles, "Id", "Name", User.UserRoles.ElementAt(0).RoleId);
return Page();
}

private async Task setDbErrorMessage(ApplicationUser dbValues,
ApplicationUser clientValues, ApplicationDbContext context)
{

if (dbValues.FirstName != clientValues.FirstName)
{
ModelState.AddModelError("User.FirstName",
$"Current value: {dbValues.FirstName}");
}

if (dbValues.LastName != clientValues.LastName)
{
ModelState.AddModelError("User.LastName",
$"Current value: {dbValues.LastName}");
}

if (dbValues.Email != clientValues.Email)
{
ModelState.AddModelError("User.Email",
$"Current value: {dbValues.Email}");
}



ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}

}


... and AssignClub.cshtml:



@page
@model AthlosifyWebArchery.Pages.Administrators.Users.AssignClubUserModel
@{
ViewData["Title"] = "Assign Club";
}
<h2>Assign Club</h2>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AssignClubUser.FirstName" class="control-label">
</label>
<input asp-for="AssignClubUser.FirstName" disabled class="form-
control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.LastName" class="control-label">
</label>
<input asp-for="AssignClubUser.LastName" disabled class="form-control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.UserName" class="control-label">
</label>
<input asp-for="AssignClubUser.UserName" disabled class="form-control" />
</div>
<div class="form-group">
<label class="control-label">Club</label>
<select asp-for="AssignClubUser.SelectedClubID" class="form-control"
asp-items="@Model.ClubNameSL">
<option value="">-- Select Club --</option>
</select>
<span asp-validation-for="AssignClubUser.SelectedClubID" class="text-danger"></span>
</div>

<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}


Environment:
.Net Core 2.2
Razor Pages



UPDATE - 1:



If we update this directly on the database by doing:



UPDATE [ClubApplicationUser]
SET ClubID = '85715C34-AFC6-4498-DA7F-08D66CAE7A01'
WHERE Id = 'ecbd27b4-03bc-4b99-82b3-76d9aa5bc7fc'


We could update this no problem. So it looks like it's contraint within the .Net core model.










share|improve this question

























  • To clarify why you can do it in the database versus not in EntityFramework. Entity Framework needs to identify an entity, it does this using the key, this is so it can keep track of various things such as changes - the SQL UPDATE statement needs the key properties in the WHERE clause. Hence the key properties make up the identity of the entity and if you change them its going to have problems. You could think about it as being a different entity and hence the create a new entity approach I suggested.

    – PhilS
    Jan 4 at 12:02











  • If you look at the EntityFrameworkCore source code in the SetPropertyModified method you can see it has explicit code blocking updates to keys and throwing InvalidOperationException

    – PhilS
    Jan 4 at 12:08













  • To my mind this is a symtom of the object-referential impedience mismatch as ClubApplicationUser is not an 'entity' - its not really responsible for its own lifecycle and should be part of the Club andor User if you were using a different more objectcentric persistence store.

    – PhilS
    Jan 4 at 12:17














2












2








2


1






I have a model called ClubApplicationUser which is bridge between the Club and ApplicationUser which is extended model of Identity User model:



public class ClubApplicationUser
{
public Guid ClubID { get; set; }

public Club Club { get; set; }

public string Id { get; set; }

public ApplicationUser ApplicationUser { get; set; }

public DateTime DateCreated { get; set; }

public string CreatedBy { get; set; }

public DateTime LastDateModified { get; set; }

public string LastModifiedBy { get; set; }

public DateTime? DateDeleted { get; set; }

public string DeletedBy { get; set; }

public bool IsDeleted { get; set; }

[Timestamp]
public byte RowVersion { get; set; }

[ForeignKey("CreatedBy")]
public ApplicationUser ClubApplicationCreatedUser { get; set; }

[ForeignKey("LastModifiedBy")]
public ApplicationUser ClubApplicationLastModifiedUser { get; set; }



}


and in the ApplicationDBContext - OnModelCreating we defined the relationships:



builder.Entity<ClubApplicationUser>()
.HasKey(bc => new { bc.ClubID, bc.Id });

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.Club)
.WithMany(b => b.ClubApplicationUsers)
.HasForeignKey(bc => bc.ClubID);

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.ApplicationUser)
.WithMany(c => c.ClubApplicationUsers)
.HasForeignKey(bc => bc.Id);


We have an issue where we could NOT update this and we have the error:




InvalidOperationException: The property 'ClubID' on entity type
'ClubApplicationUser' is part of a key and so cannot be modified or
marked as modified. To change the principal of an existing entity with
an identifying foreign key first delete the dependent and invoke
'SaveChanges' then associate the dependent with the new principal.




Here's the AssignClub.cs:



public class AssignClubUserModel : ClubNamePageModel
{
private readonly AthlosifyWebArchery.Data.ApplicationDbContext _context;


public AssignClubUserModel(AthlosifyWebArchery.Data.ApplicationDbContext context)
{
_context = context;
}

public class AssignClubUserViewModel<ApplicationUser>
{

public string FirstName { get; set; }
public string LastName { get; set; }

public string UserName { get; set; }

public Guid SelectedClubID { get; set; }

public byte RowVersion { get; set; }

}

[BindProperty]
public AssignClubUserViewModel<ApplicationUser> AssignClubUser { get; set; }

public SelectList ClubNameSL { get; set; }

public async Task<IActionResult> OnGetAsync(Guid? id)
{



if (id == null)
return NotFound();

var user = await _context.Users
.Include(u => u.ClubApplicationUsers)
.Where(t => t.Id == id.ToString())
.Select(t => new AssignClubUserViewModel<ApplicationUser>
{
FirstName = t.FirstName,
LastName = t.LastName,
UserName = t.UserName,
SelectedClubID = t.ClubApplicationUsers.ElementAt(0).ClubID,
RowVersion = t.RowVersion
}).SingleAsync();


AssignClubUser = user;



// Use strongly typed data rather than ViewData.
ClubNameSL = new SelectList(_context.Club, "ClubID", "Name");

//PopulateClubsDropDownList(_context);

return Page();
}

public async Task<IActionResult> OnPostAsync(Guid id)
{
if (!ModelState.IsValid)
{
return Page();
}

// 1st approach:
// Modify the bridge model directly

var clubApplicationUserToUpdate = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());

if (clubApplicationUserToUpdate == null)
{
return await HandleDeletedUser();
}

_context.Entry(clubApplicationUserToUpdate)
.Property("RowVersion").OriginalValue = AssignClubUser.RowVersion;

_context.Entry(clubApplicationUserToUpdate)
.Property("ClubID").OriginalValue = AssignClubUser.SelectedClubID;

await _context.SaveChangesAsync();


// 2nd approach:
// Soft -Delete and Add
// Did the soft-deleting and managed to add a new one BUT then die the roll back (adding the old one)
// Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.
// Cannot insert duplicate key in object
// Due to duplicate key

/*var clubApplicatonUserToRemove = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());
ClubApplicationUser clubApplicatonUserToAdd = new ClubApplicationUser();
clubApplicatonUserToAdd.Id = id.ToString();
clubApplicatonUserToAdd.ClubID = AssignClubUser.SelectedClubID;


//_context.Entry(clubApplicatonUserToRemove)
// .Property("RowVersion").OriginalValue = User.RowVersion;

if (clubApplicatonUserToRemove != null)
{
_context.ClubApplicationUser.Remove(clubApplicatonUserToRemove);
await _context.SaveChangesAsync();
_context.ClubApplicationUser.Add(clubApplicatonUserToAdd);
await _context.SaveChangesAsync();
}*/




return Page();
}

private async Task<IActionResult> HandleDeletedUser()
{
//ClubA deletedClubApplicationUser = new ApplicationUser();
//ModelState.AddModelError(string.Empty,
// "Unable to save. The user was deleted by another user.");
//ClubNameSL = new SelectList(_context.Roles, "Id", "Name", User.UserRoles.ElementAt(0).RoleId);
return Page();
}

private async Task setDbErrorMessage(ApplicationUser dbValues,
ApplicationUser clientValues, ApplicationDbContext context)
{

if (dbValues.FirstName != clientValues.FirstName)
{
ModelState.AddModelError("User.FirstName",
$"Current value: {dbValues.FirstName}");
}

if (dbValues.LastName != clientValues.LastName)
{
ModelState.AddModelError("User.LastName",
$"Current value: {dbValues.LastName}");
}

if (dbValues.Email != clientValues.Email)
{
ModelState.AddModelError("User.Email",
$"Current value: {dbValues.Email}");
}



ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}

}


... and AssignClub.cshtml:



@page
@model AthlosifyWebArchery.Pages.Administrators.Users.AssignClubUserModel
@{
ViewData["Title"] = "Assign Club";
}
<h2>Assign Club</h2>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AssignClubUser.FirstName" class="control-label">
</label>
<input asp-for="AssignClubUser.FirstName" disabled class="form-
control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.LastName" class="control-label">
</label>
<input asp-for="AssignClubUser.LastName" disabled class="form-control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.UserName" class="control-label">
</label>
<input asp-for="AssignClubUser.UserName" disabled class="form-control" />
</div>
<div class="form-group">
<label class="control-label">Club</label>
<select asp-for="AssignClubUser.SelectedClubID" class="form-control"
asp-items="@Model.ClubNameSL">
<option value="">-- Select Club --</option>
</select>
<span asp-validation-for="AssignClubUser.SelectedClubID" class="text-danger"></span>
</div>

<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}


Environment:
.Net Core 2.2
Razor Pages



UPDATE - 1:



If we update this directly on the database by doing:



UPDATE [ClubApplicationUser]
SET ClubID = '85715C34-AFC6-4498-DA7F-08D66CAE7A01'
WHERE Id = 'ecbd27b4-03bc-4b99-82b3-76d9aa5bc7fc'


We could update this no problem. So it looks like it's contraint within the .Net core model.










share|improve this question
















I have a model called ClubApplicationUser which is bridge between the Club and ApplicationUser which is extended model of Identity User model:



public class ClubApplicationUser
{
public Guid ClubID { get; set; }

public Club Club { get; set; }

public string Id { get; set; }

public ApplicationUser ApplicationUser { get; set; }

public DateTime DateCreated { get; set; }

public string CreatedBy { get; set; }

public DateTime LastDateModified { get; set; }

public string LastModifiedBy { get; set; }

public DateTime? DateDeleted { get; set; }

public string DeletedBy { get; set; }

public bool IsDeleted { get; set; }

[Timestamp]
public byte RowVersion { get; set; }

[ForeignKey("CreatedBy")]
public ApplicationUser ClubApplicationCreatedUser { get; set; }

[ForeignKey("LastModifiedBy")]
public ApplicationUser ClubApplicationLastModifiedUser { get; set; }



}


and in the ApplicationDBContext - OnModelCreating we defined the relationships:



builder.Entity<ClubApplicationUser>()
.HasKey(bc => new { bc.ClubID, bc.Id });

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.Club)
.WithMany(b => b.ClubApplicationUsers)
.HasForeignKey(bc => bc.ClubID);

builder.Entity<ClubApplicationUser>()
.HasOne(bc => bc.ApplicationUser)
.WithMany(c => c.ClubApplicationUsers)
.HasForeignKey(bc => bc.Id);


We have an issue where we could NOT update this and we have the error:




InvalidOperationException: The property 'ClubID' on entity type
'ClubApplicationUser' is part of a key and so cannot be modified or
marked as modified. To change the principal of an existing entity with
an identifying foreign key first delete the dependent and invoke
'SaveChanges' then associate the dependent with the new principal.




Here's the AssignClub.cs:



public class AssignClubUserModel : ClubNamePageModel
{
private readonly AthlosifyWebArchery.Data.ApplicationDbContext _context;


public AssignClubUserModel(AthlosifyWebArchery.Data.ApplicationDbContext context)
{
_context = context;
}

public class AssignClubUserViewModel<ApplicationUser>
{

public string FirstName { get; set; }
public string LastName { get; set; }

public string UserName { get; set; }

public Guid SelectedClubID { get; set; }

public byte RowVersion { get; set; }

}

[BindProperty]
public AssignClubUserViewModel<ApplicationUser> AssignClubUser { get; set; }

public SelectList ClubNameSL { get; set; }

public async Task<IActionResult> OnGetAsync(Guid? id)
{



if (id == null)
return NotFound();

var user = await _context.Users
.Include(u => u.ClubApplicationUsers)
.Where(t => t.Id == id.ToString())
.Select(t => new AssignClubUserViewModel<ApplicationUser>
{
FirstName = t.FirstName,
LastName = t.LastName,
UserName = t.UserName,
SelectedClubID = t.ClubApplicationUsers.ElementAt(0).ClubID,
RowVersion = t.RowVersion
}).SingleAsync();


AssignClubUser = user;



// Use strongly typed data rather than ViewData.
ClubNameSL = new SelectList(_context.Club, "ClubID", "Name");

//PopulateClubsDropDownList(_context);

return Page();
}

public async Task<IActionResult> OnPostAsync(Guid id)
{
if (!ModelState.IsValid)
{
return Page();
}

// 1st approach:
// Modify the bridge model directly

var clubApplicationUserToUpdate = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());

if (clubApplicationUserToUpdate == null)
{
return await HandleDeletedUser();
}

_context.Entry(clubApplicationUserToUpdate)
.Property("RowVersion").OriginalValue = AssignClubUser.RowVersion;

_context.Entry(clubApplicationUserToUpdate)
.Property("ClubID").OriginalValue = AssignClubUser.SelectedClubID;

await _context.SaveChangesAsync();


// 2nd approach:
// Soft -Delete and Add
// Did the soft-deleting and managed to add a new one BUT then die the roll back (adding the old one)
// Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.
// Cannot insert duplicate key in object
// Due to duplicate key

/*var clubApplicatonUserToRemove = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());
ClubApplicationUser clubApplicatonUserToAdd = new ClubApplicationUser();
clubApplicatonUserToAdd.Id = id.ToString();
clubApplicatonUserToAdd.ClubID = AssignClubUser.SelectedClubID;


//_context.Entry(clubApplicatonUserToRemove)
// .Property("RowVersion").OriginalValue = User.RowVersion;

if (clubApplicatonUserToRemove != null)
{
_context.ClubApplicationUser.Remove(clubApplicatonUserToRemove);
await _context.SaveChangesAsync();
_context.ClubApplicationUser.Add(clubApplicatonUserToAdd);
await _context.SaveChangesAsync();
}*/




return Page();
}

private async Task<IActionResult> HandleDeletedUser()
{
//ClubA deletedClubApplicationUser = new ApplicationUser();
//ModelState.AddModelError(string.Empty,
// "Unable to save. The user was deleted by another user.");
//ClubNameSL = new SelectList(_context.Roles, "Id", "Name", User.UserRoles.ElementAt(0).RoleId);
return Page();
}

private async Task setDbErrorMessage(ApplicationUser dbValues,
ApplicationUser clientValues, ApplicationDbContext context)
{

if (dbValues.FirstName != clientValues.FirstName)
{
ModelState.AddModelError("User.FirstName",
$"Current value: {dbValues.FirstName}");
}

if (dbValues.LastName != clientValues.LastName)
{
ModelState.AddModelError("User.LastName",
$"Current value: {dbValues.LastName}");
}

if (dbValues.Email != clientValues.Email)
{
ModelState.AddModelError("User.Email",
$"Current value: {dbValues.Email}");
}



ModelState.AddModelError(string.Empty,
"The record you attempted to edit "
+ "was modified by another user after you. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again.");
}

}


... and AssignClub.cshtml:



@page
@model AthlosifyWebArchery.Pages.Administrators.Users.AssignClubUserModel
@{
ViewData["Title"] = "Assign Club";
}
<h2>Assign Club</h2>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AssignClubUser.FirstName" class="control-label">
</label>
<input asp-for="AssignClubUser.FirstName" disabled class="form-
control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.LastName" class="control-label">
</label>
<input asp-for="AssignClubUser.LastName" disabled class="form-control" />
</div>
<div class="form-group">
<label asp-for="AssignClubUser.UserName" class="control-label">
</label>
<input asp-for="AssignClubUser.UserName" disabled class="form-control" />
</div>
<div class="form-group">
<label class="control-label">Club</label>
<select asp-for="AssignClubUser.SelectedClubID" class="form-control"
asp-items="@Model.ClubNameSL">
<option value="">-- Select Club --</option>
</select>
<span asp-validation-for="AssignClubUser.SelectedClubID" class="text-danger"></span>
</div>

<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}


Environment:
.Net Core 2.2
Razor Pages



UPDATE - 1:



If we update this directly on the database by doing:



UPDATE [ClubApplicationUser]
SET ClubID = '85715C34-AFC6-4498-DA7F-08D66CAE7A01'
WHERE Id = 'ecbd27b4-03bc-4b99-82b3-76d9aa5bc7fc'


We could update this no problem. So it looks like it's contraint within the .Net core model.







.net-core






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 1 at 23:42







dcpartners

















asked Dec 31 '18 at 11:28









dcpartnersdcpartners

1,56783346




1,56783346













  • To clarify why you can do it in the database versus not in EntityFramework. Entity Framework needs to identify an entity, it does this using the key, this is so it can keep track of various things such as changes - the SQL UPDATE statement needs the key properties in the WHERE clause. Hence the key properties make up the identity of the entity and if you change them its going to have problems. You could think about it as being a different entity and hence the create a new entity approach I suggested.

    – PhilS
    Jan 4 at 12:02











  • If you look at the EntityFrameworkCore source code in the SetPropertyModified method you can see it has explicit code blocking updates to keys and throwing InvalidOperationException

    – PhilS
    Jan 4 at 12:08













  • To my mind this is a symtom of the object-referential impedience mismatch as ClubApplicationUser is not an 'entity' - its not really responsible for its own lifecycle and should be part of the Club andor User if you were using a different more objectcentric persistence store.

    – PhilS
    Jan 4 at 12:17



















  • To clarify why you can do it in the database versus not in EntityFramework. Entity Framework needs to identify an entity, it does this using the key, this is so it can keep track of various things such as changes - the SQL UPDATE statement needs the key properties in the WHERE clause. Hence the key properties make up the identity of the entity and if you change them its going to have problems. You could think about it as being a different entity and hence the create a new entity approach I suggested.

    – PhilS
    Jan 4 at 12:02











  • If you look at the EntityFrameworkCore source code in the SetPropertyModified method you can see it has explicit code blocking updates to keys and throwing InvalidOperationException

    – PhilS
    Jan 4 at 12:08













  • To my mind this is a symtom of the object-referential impedience mismatch as ClubApplicationUser is not an 'entity' - its not really responsible for its own lifecycle and should be part of the Club andor User if you were using a different more objectcentric persistence store.

    – PhilS
    Jan 4 at 12:17

















To clarify why you can do it in the database versus not in EntityFramework. Entity Framework needs to identify an entity, it does this using the key, this is so it can keep track of various things such as changes - the SQL UPDATE statement needs the key properties in the WHERE clause. Hence the key properties make up the identity of the entity and if you change them its going to have problems. You could think about it as being a different entity and hence the create a new entity approach I suggested.

– PhilS
Jan 4 at 12:02





To clarify why you can do it in the database versus not in EntityFramework. Entity Framework needs to identify an entity, it does this using the key, this is so it can keep track of various things such as changes - the SQL UPDATE statement needs the key properties in the WHERE clause. Hence the key properties make up the identity of the entity and if you change them its going to have problems. You could think about it as being a different entity and hence the create a new entity approach I suggested.

– PhilS
Jan 4 at 12:02













If you look at the EntityFrameworkCore source code in the SetPropertyModified method you can see it has explicit code blocking updates to keys and throwing InvalidOperationException

– PhilS
Jan 4 at 12:08







If you look at the EntityFrameworkCore source code in the SetPropertyModified method you can see it has explicit code blocking updates to keys and throwing InvalidOperationException

– PhilS
Jan 4 at 12:08















To my mind this is a symtom of the object-referential impedience mismatch as ClubApplicationUser is not an 'entity' - its not really responsible for its own lifecycle and should be part of the Club andor User if you were using a different more objectcentric persistence store.

– PhilS
Jan 4 at 12:17





To my mind this is a symtom of the object-referential impedience mismatch as ClubApplicationUser is not an 'entity' - its not really responsible for its own lifecycle and should be part of the Club andor User if you were using a different more objectcentric persistence store.

– PhilS
Jan 4 at 12:17












4 Answers
4






active

oldest

votes


















2





+25









I think the best solution is that you need to Delete and Insert instead of updating although given your ClubApplicationUser actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete.



If you think of it in the logic of your domain, I don't think a user generally changes being a member of one club to another, they leave (delete) one club and join (insert) another.



Although I could come up with another domain where it does make sense to update so I don't think this is a good generic argument.



The following code shows a cutdown version of your problem. You can see that the Tests allow an Insert and Delete but fail with an Update



public class Club
{
public int Id { get; set; }
public string Name { get; set; }

public IList<ClubUser> Users { get; set; }
}

public class User
{
public int Id { get; set; }

public string Name { get; set; }

public IList<ClubUser> Clubs { get; set; }
}

public class ClubUser
{
public int ClubID { get; set; }

public Club Club { get; set; }

public int Id { get; set; }

public User User { get; set; }

public string Extra { get; set; }
}

public class ApplicationDbContext : Microsoft.EntityFrameworkCore.DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Club> Clubs { get; set; }
public DbSet<ClubUser> ClubUsers { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=.;Database=Spike;Trusted_Connection=True;");
}

protected override void OnModelCreating(Microsoft.EntityFrameworkCore.ModelBuilder builder)
{
builder.Entity<Club>()
.HasKey(c => c.Id );

builder.Entity<User>()
.HasKey(c => c.Id );

builder.Entity<ClubUser>()
.HasKey(cu => new { cu.ClubID, cu.Id });

builder.Entity<ClubUser>()
.HasOne<Club>(cu => cu.Club)
.WithMany(u => u.Users)
.HasForeignKey(bc => bc.ClubID);

builder.Entity<ClubUser>()
.HasOne<User>(cu => cu.User)
.WithMany(c => c.Clubs)
.HasForeignKey(cu => cu.Id);

}
}

[TestClass]
public class ManyToMany
{
[TestMethod]
public void DeleteAndInsert()
{
var context = new ApplicationDbContext();

var clubusers = context.ClubUsers;
var clubs = context.Clubs;
var users = context.Users;

var original = clubusers.First();
clubusers.Remove(original);

var newClubUser = new ClubUser
{
Club = clubs.Last(),
User = users.First(),
Extra = "Another"
};

clubusers.Add(newClubUser);

context.SaveChanges();
}

[TestMethod]
public void Update()
{
var context = new ApplicationDbContext();

var clubusers = context.ClubUsers;
var clubs = context.Clubs;
var users = context.Users;

var update = clubusers.First();
update.Club = clubs.Last();
update.Extra = "Changed";

Assert.ThrowsException<InvalidOperationException>( () => context.SaveChanges());
}
}


To initialise the test database:



ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_User]
GO

ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_Club]
GO

DROP TABLE [dbo].[ClubUsers]
GO

DROP TABLE [dbo].[Clubs]
GO

DROP TABLE [dbo].[Users]
GO

CREATE TABLE [dbo].[Clubs](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Club] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Users](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[ClubUsers](
[ClubId] [int] NOT NULL,
[Id] [int] NOT NULL,
[Extra] [varchar](50) NOT NULL,
CONSTRAINT [PK_ClubUser] PRIMARY KEY CLUSTERED
(
[ClubId] ASC,
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_Club] FOREIGN KEY([ClubId])
REFERENCES [dbo].[Clubs] ([Id])
GO

ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_Club]
GO

ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_User] FOREIGN KEY([Id])
REFERENCES [dbo].[Users] ([Id])
GO

ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_User]
GO

INSERT Clubs(Name)
VALUES ('GlenEagles');

INSERT Clubs(Name)
VALUES ('StAndrews');

INSERT Clubs(Name)
VALUES ('Wentworth');

INSERT dbo.[Users](Name)
VALUES ('Pete');

INSERT dbo.[Users](Name)
VALUES ('Dave');

INSERT ClubUsers(ClubId, Id, Extra)
VALUES (1,1, 'Hello');





share|improve this answer
























  • As on domain using Soft-Delete approach .. we could not do the Hard-Delete and then Create approach. It's quite interesting ... if we do this at the database level (see UPDATE - 1), it worked well BUT not the code level.

    – dcpartners
    Jan 3 at 20:37











  • That was mwhat I suspectedwhen I mentioned 'actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete'. In that case you would change tthe original to mark it as deleted (setting the IsDeleted flag) and create a new one cloned from the original. Does that satisfy your domain or must you update the existing record?

    – PhilS
    Jan 4 at 11:05





















2














* THIS DOES NOT WORK - see comment *



My third option which is the quickest for you to implement however i am not sure about all the implications.



If you change OnModelCreating to set an index instead of a key



i.e.



        builder.Entity<ClubUser>()
.HasKey(cu => new { cu.ClubID, cu.Id });


becomes



        builder.Entity<ClubUser>()
.HasIndex(cu => new { cu.ClubID, cu.Id });


The update will now work but then you do not have a key on the ClubUser which may cause other problems.






share|improve this answer


























  • I now understand this better, without setting the key it is now implicitely making the Id field the key (i.e. the User Id) due to the name of the property - if it had been called UserId instead you would have got an error when instanciating the context that there was no primary key.

    – PhilS
    Jan 4 at 12:26











  • The implication of this is that you cannot change the User as it changes the Id property, only the Club and if you have a User with more than one club it will update all of them in the database which is bad.

    – PhilS
    Jan 4 at 12:29



















2














About:




InvalidOperationException: The property 'ClubID' on entity type
'ClubApplicationUser' is part of a key...




PrimaryKey in ClubApplicationUsers table is both ClubID and Id.
You can't just make changes to existing records by Id.



For example this:



var clubApplicationUserToUpdate = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString());


Must be like this:



var clubApplicationUserToUpdate = await _context.ClubApplicationUser
.FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString());


Or:



var clubApplicationUsersToUpdate = await _context.ClubApplicationUser
.Where(m => m.Id == id.ToString()).ToList();


About:




2nd approach:

...

Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.




I'll explain with example:



Clubs: 1, 2, 3
ApplicationUsers: A, B, C
ClubApplicationUser: A1, A2


Trying to remove A1, and add A2 - it says A2 already exists.



Solution is closer to the 2nd approach:



public async Task<IActionResult> OnPostAsync(Guid id)
{
if (!this.ModelState.IsValid)
{
return Page();
}

//delete all club memberships and add new one
var clubApplicatonUsersToRemove = await _context.ClubApplicationUser
.Where(m => m.Id == id.ToString()).ToList();

foreach (var clubApplicatonUser in clubApplicatonUsersToRemove)
{
_context.ClubApplicationUser.Remove(clubApplicatonUser);
}

_context.ClubApplicationUser.Add(new ClubApplicationUser()
{
Id = id.ToString(),
ClubID = AssignClubUser.SelectedClubID
});

await _context.SaveChangesAsync();

return Page();
}


If you don't want to delete anything, but just add new record:



public async Task<IActionResult> OnPostAsync(Guid id)
{
if (!this.ModelState.IsValid)
{
return Page();
}

// dont delete, just add new one
var clubApplicatonUserExists = await _context.ClubApplicationUser
.Where(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID).FirstOrDefaultAsync();


if (clubApplicatonUserExists == null)
{
_context.ClubApplicationUser.Add(new ClubApplicationUser()
{
Id = id.ToString(),
ClubID = AssignClubUser.SelectedClubID
});

await _context.SaveChangesAsync();
}

return Page();
}





share|improve this answer


























  • With this approach - "don't want to delete anything, but just add new record" ... how do we differentiate this then when we get the list for instance (.FirstOrDefaultAsync)?

    – dcpartners
    Jan 8 at 21:23













  • With this approach - "Solution is closer to the 2nd approach:" above, we have a soft-deleted approach that we want to keep the record and this might work.

    – dcpartners
    Jan 8 at 21:36











  • I din't get exactly what you need to achieve. My examples are just to explain the problem and provide working example code. You can toon it to work for you, or provide exactly what you need to delete and what to keep/create.

    – Obelixx
    Jan 9 at 7:43











  • Sorry for the late reply. I did what you suggest in term of : var clubApplicationUserToUpdate = await _context.ClubApplicationUser .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString()); but in this case SelectedClubID we changed to originalClubID ... but when we save still have the same issue?

    – dcpartners
    Jan 11 at 20:42











  • What is the primary goal? (delete all club relations to user or delete one club related to user, and then what - add selected if it dosen't exist) How you get the ClubId that needs to be deleted?

    – Obelixx
    Jan 15 at 11:36



















1














Another solution if you have control of the database schema is to add a surragate key to the link table.



Then if you need to update the club or user you are not changing the entity unique identifier and hence it will be allowed.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53986919%2fneed-a-help-to-update-the-model%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2





    +25









    I think the best solution is that you need to Delete and Insert instead of updating although given your ClubApplicationUser actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete.



    If you think of it in the logic of your domain, I don't think a user generally changes being a member of one club to another, they leave (delete) one club and join (insert) another.



    Although I could come up with another domain where it does make sense to update so I don't think this is a good generic argument.



    The following code shows a cutdown version of your problem. You can see that the Tests allow an Insert and Delete but fail with an Update



    public class Club
    {
    public int Id { get; set; }
    public string Name { get; set; }

    public IList<ClubUser> Users { get; set; }
    }

    public class User
    {
    public int Id { get; set; }

    public string Name { get; set; }

    public IList<ClubUser> Clubs { get; set; }
    }

    public class ClubUser
    {
    public int ClubID { get; set; }

    public Club Club { get; set; }

    public int Id { get; set; }

    public User User { get; set; }

    public string Extra { get; set; }
    }

    public class ApplicationDbContext : Microsoft.EntityFrameworkCore.DbContext
    {
    public DbSet<User> Users { get; set; }
    public DbSet<Club> Clubs { get; set; }
    public DbSet<ClubUser> ClubUsers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    optionsBuilder.UseSqlServer(@"Server=.;Database=Spike;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(Microsoft.EntityFrameworkCore.ModelBuilder builder)
    {
    builder.Entity<Club>()
    .HasKey(c => c.Id );

    builder.Entity<User>()
    .HasKey(c => c.Id );

    builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });

    builder.Entity<ClubUser>()
    .HasOne<Club>(cu => cu.Club)
    .WithMany(u => u.Users)
    .HasForeignKey(bc => bc.ClubID);

    builder.Entity<ClubUser>()
    .HasOne<User>(cu => cu.User)
    .WithMany(c => c.Clubs)
    .HasForeignKey(cu => cu.Id);

    }
    }

    [TestClass]
    public class ManyToMany
    {
    [TestMethod]
    public void DeleteAndInsert()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var original = clubusers.First();
    clubusers.Remove(original);

    var newClubUser = new ClubUser
    {
    Club = clubs.Last(),
    User = users.First(),
    Extra = "Another"
    };

    clubusers.Add(newClubUser);

    context.SaveChanges();
    }

    [TestMethod]
    public void Update()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var update = clubusers.First();
    update.Club = clubs.Last();
    update.Extra = "Changed";

    Assert.ThrowsException<InvalidOperationException>( () => context.SaveChanges());
    }
    }


    To initialise the test database:



    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_User]
    GO

    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_Club]
    GO

    DROP TABLE [dbo].[ClubUsers]
    GO

    DROP TABLE [dbo].[Clubs]
    GO

    DROP TABLE [dbo].[Users]
    GO

    CREATE TABLE [dbo].[Clubs](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_Club] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[Users](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[ClubUsers](
    [ClubId] [int] NOT NULL,
    [Id] [int] NOT NULL,
    [Extra] [varchar](50) NOT NULL,
    CONSTRAINT [PK_ClubUser] PRIMARY KEY CLUSTERED
    (
    [ClubId] ASC,
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_Club] FOREIGN KEY([ClubId])
    REFERENCES [dbo].[Clubs] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_Club]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_User] FOREIGN KEY([Id])
    REFERENCES [dbo].[Users] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_User]
    GO

    INSERT Clubs(Name)
    VALUES ('GlenEagles');

    INSERT Clubs(Name)
    VALUES ('StAndrews');

    INSERT Clubs(Name)
    VALUES ('Wentworth');

    INSERT dbo.[Users](Name)
    VALUES ('Pete');

    INSERT dbo.[Users](Name)
    VALUES ('Dave');

    INSERT ClubUsers(ClubId, Id, Extra)
    VALUES (1,1, 'Hello');





    share|improve this answer
























    • As on domain using Soft-Delete approach .. we could not do the Hard-Delete and then Create approach. It's quite interesting ... if we do this at the database level (see UPDATE - 1), it worked well BUT not the code level.

      – dcpartners
      Jan 3 at 20:37











    • That was mwhat I suspectedwhen I mentioned 'actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete'. In that case you would change tthe original to mark it as deleted (setting the IsDeleted flag) and create a new one cloned from the original. Does that satisfy your domain or must you update the existing record?

      – PhilS
      Jan 4 at 11:05


















    2





    +25









    I think the best solution is that you need to Delete and Insert instead of updating although given your ClubApplicationUser actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete.



    If you think of it in the logic of your domain, I don't think a user generally changes being a member of one club to another, they leave (delete) one club and join (insert) another.



    Although I could come up with another domain where it does make sense to update so I don't think this is a good generic argument.



    The following code shows a cutdown version of your problem. You can see that the Tests allow an Insert and Delete but fail with an Update



    public class Club
    {
    public int Id { get; set; }
    public string Name { get; set; }

    public IList<ClubUser> Users { get; set; }
    }

    public class User
    {
    public int Id { get; set; }

    public string Name { get; set; }

    public IList<ClubUser> Clubs { get; set; }
    }

    public class ClubUser
    {
    public int ClubID { get; set; }

    public Club Club { get; set; }

    public int Id { get; set; }

    public User User { get; set; }

    public string Extra { get; set; }
    }

    public class ApplicationDbContext : Microsoft.EntityFrameworkCore.DbContext
    {
    public DbSet<User> Users { get; set; }
    public DbSet<Club> Clubs { get; set; }
    public DbSet<ClubUser> ClubUsers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    optionsBuilder.UseSqlServer(@"Server=.;Database=Spike;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(Microsoft.EntityFrameworkCore.ModelBuilder builder)
    {
    builder.Entity<Club>()
    .HasKey(c => c.Id );

    builder.Entity<User>()
    .HasKey(c => c.Id );

    builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });

    builder.Entity<ClubUser>()
    .HasOne<Club>(cu => cu.Club)
    .WithMany(u => u.Users)
    .HasForeignKey(bc => bc.ClubID);

    builder.Entity<ClubUser>()
    .HasOne<User>(cu => cu.User)
    .WithMany(c => c.Clubs)
    .HasForeignKey(cu => cu.Id);

    }
    }

    [TestClass]
    public class ManyToMany
    {
    [TestMethod]
    public void DeleteAndInsert()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var original = clubusers.First();
    clubusers.Remove(original);

    var newClubUser = new ClubUser
    {
    Club = clubs.Last(),
    User = users.First(),
    Extra = "Another"
    };

    clubusers.Add(newClubUser);

    context.SaveChanges();
    }

    [TestMethod]
    public void Update()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var update = clubusers.First();
    update.Club = clubs.Last();
    update.Extra = "Changed";

    Assert.ThrowsException<InvalidOperationException>( () => context.SaveChanges());
    }
    }


    To initialise the test database:



    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_User]
    GO

    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_Club]
    GO

    DROP TABLE [dbo].[ClubUsers]
    GO

    DROP TABLE [dbo].[Clubs]
    GO

    DROP TABLE [dbo].[Users]
    GO

    CREATE TABLE [dbo].[Clubs](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_Club] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[Users](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[ClubUsers](
    [ClubId] [int] NOT NULL,
    [Id] [int] NOT NULL,
    [Extra] [varchar](50) NOT NULL,
    CONSTRAINT [PK_ClubUser] PRIMARY KEY CLUSTERED
    (
    [ClubId] ASC,
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_Club] FOREIGN KEY([ClubId])
    REFERENCES [dbo].[Clubs] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_Club]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_User] FOREIGN KEY([Id])
    REFERENCES [dbo].[Users] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_User]
    GO

    INSERT Clubs(Name)
    VALUES ('GlenEagles');

    INSERT Clubs(Name)
    VALUES ('StAndrews');

    INSERT Clubs(Name)
    VALUES ('Wentworth');

    INSERT dbo.[Users](Name)
    VALUES ('Pete');

    INSERT dbo.[Users](Name)
    VALUES ('Dave');

    INSERT ClubUsers(ClubId, Id, Extra)
    VALUES (1,1, 'Hello');





    share|improve this answer
























    • As on domain using Soft-Delete approach .. we could not do the Hard-Delete and then Create approach. It's quite interesting ... if we do this at the database level (see UPDATE - 1), it worked well BUT not the code level.

      – dcpartners
      Jan 3 at 20:37











    • That was mwhat I suspectedwhen I mentioned 'actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete'. In that case you would change tthe original to mark it as deleted (setting the IsDeleted flag) and create a new one cloned from the original. Does that satisfy your domain or must you update the existing record?

      – PhilS
      Jan 4 at 11:05
















    2





    +25







    2





    +25



    2




    +25





    I think the best solution is that you need to Delete and Insert instead of updating although given your ClubApplicationUser actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete.



    If you think of it in the logic of your domain, I don't think a user generally changes being a member of one club to another, they leave (delete) one club and join (insert) another.



    Although I could come up with another domain where it does make sense to update so I don't think this is a good generic argument.



    The following code shows a cutdown version of your problem. You can see that the Tests allow an Insert and Delete but fail with an Update



    public class Club
    {
    public int Id { get; set; }
    public string Name { get; set; }

    public IList<ClubUser> Users { get; set; }
    }

    public class User
    {
    public int Id { get; set; }

    public string Name { get; set; }

    public IList<ClubUser> Clubs { get; set; }
    }

    public class ClubUser
    {
    public int ClubID { get; set; }

    public Club Club { get; set; }

    public int Id { get; set; }

    public User User { get; set; }

    public string Extra { get; set; }
    }

    public class ApplicationDbContext : Microsoft.EntityFrameworkCore.DbContext
    {
    public DbSet<User> Users { get; set; }
    public DbSet<Club> Clubs { get; set; }
    public DbSet<ClubUser> ClubUsers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    optionsBuilder.UseSqlServer(@"Server=.;Database=Spike;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(Microsoft.EntityFrameworkCore.ModelBuilder builder)
    {
    builder.Entity<Club>()
    .HasKey(c => c.Id );

    builder.Entity<User>()
    .HasKey(c => c.Id );

    builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });

    builder.Entity<ClubUser>()
    .HasOne<Club>(cu => cu.Club)
    .WithMany(u => u.Users)
    .HasForeignKey(bc => bc.ClubID);

    builder.Entity<ClubUser>()
    .HasOne<User>(cu => cu.User)
    .WithMany(c => c.Clubs)
    .HasForeignKey(cu => cu.Id);

    }
    }

    [TestClass]
    public class ManyToMany
    {
    [TestMethod]
    public void DeleteAndInsert()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var original = clubusers.First();
    clubusers.Remove(original);

    var newClubUser = new ClubUser
    {
    Club = clubs.Last(),
    User = users.First(),
    Extra = "Another"
    };

    clubusers.Add(newClubUser);

    context.SaveChanges();
    }

    [TestMethod]
    public void Update()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var update = clubusers.First();
    update.Club = clubs.Last();
    update.Extra = "Changed";

    Assert.ThrowsException<InvalidOperationException>( () => context.SaveChanges());
    }
    }


    To initialise the test database:



    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_User]
    GO

    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_Club]
    GO

    DROP TABLE [dbo].[ClubUsers]
    GO

    DROP TABLE [dbo].[Clubs]
    GO

    DROP TABLE [dbo].[Users]
    GO

    CREATE TABLE [dbo].[Clubs](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_Club] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[Users](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[ClubUsers](
    [ClubId] [int] NOT NULL,
    [Id] [int] NOT NULL,
    [Extra] [varchar](50) NOT NULL,
    CONSTRAINT [PK_ClubUser] PRIMARY KEY CLUSTERED
    (
    [ClubId] ASC,
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_Club] FOREIGN KEY([ClubId])
    REFERENCES [dbo].[Clubs] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_Club]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_User] FOREIGN KEY([Id])
    REFERENCES [dbo].[Users] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_User]
    GO

    INSERT Clubs(Name)
    VALUES ('GlenEagles');

    INSERT Clubs(Name)
    VALUES ('StAndrews');

    INSERT Clubs(Name)
    VALUES ('Wentworth');

    INSERT dbo.[Users](Name)
    VALUES ('Pete');

    INSERT dbo.[Users](Name)
    VALUES ('Dave');

    INSERT ClubUsers(ClubId, Id, Extra)
    VALUES (1,1, 'Hello');





    share|improve this answer













    I think the best solution is that you need to Delete and Insert instead of updating although given your ClubApplicationUser actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete.



    If you think of it in the logic of your domain, I don't think a user generally changes being a member of one club to another, they leave (delete) one club and join (insert) another.



    Although I could come up with another domain where it does make sense to update so I don't think this is a good generic argument.



    The following code shows a cutdown version of your problem. You can see that the Tests allow an Insert and Delete but fail with an Update



    public class Club
    {
    public int Id { get; set; }
    public string Name { get; set; }

    public IList<ClubUser> Users { get; set; }
    }

    public class User
    {
    public int Id { get; set; }

    public string Name { get; set; }

    public IList<ClubUser> Clubs { get; set; }
    }

    public class ClubUser
    {
    public int ClubID { get; set; }

    public Club Club { get; set; }

    public int Id { get; set; }

    public User User { get; set; }

    public string Extra { get; set; }
    }

    public class ApplicationDbContext : Microsoft.EntityFrameworkCore.DbContext
    {
    public DbSet<User> Users { get; set; }
    public DbSet<Club> Clubs { get; set; }
    public DbSet<ClubUser> ClubUsers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    optionsBuilder.UseSqlServer(@"Server=.;Database=Spike;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(Microsoft.EntityFrameworkCore.ModelBuilder builder)
    {
    builder.Entity<Club>()
    .HasKey(c => c.Id );

    builder.Entity<User>()
    .HasKey(c => c.Id );

    builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });

    builder.Entity<ClubUser>()
    .HasOne<Club>(cu => cu.Club)
    .WithMany(u => u.Users)
    .HasForeignKey(bc => bc.ClubID);

    builder.Entity<ClubUser>()
    .HasOne<User>(cu => cu.User)
    .WithMany(c => c.Clubs)
    .HasForeignKey(cu => cu.Id);

    }
    }

    [TestClass]
    public class ManyToMany
    {
    [TestMethod]
    public void DeleteAndInsert()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var original = clubusers.First();
    clubusers.Remove(original);

    var newClubUser = new ClubUser
    {
    Club = clubs.Last(),
    User = users.First(),
    Extra = "Another"
    };

    clubusers.Add(newClubUser);

    context.SaveChanges();
    }

    [TestMethod]
    public void Update()
    {
    var context = new ApplicationDbContext();

    var clubusers = context.ClubUsers;
    var clubs = context.Clubs;
    var users = context.Users;

    var update = clubusers.First();
    update.Club = clubs.Last();
    update.Extra = "Changed";

    Assert.ThrowsException<InvalidOperationException>( () => context.SaveChanges());
    }
    }


    To initialise the test database:



    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_User]
    GO

    ALTER TABLE [dbo].[ClubUsers] DROP CONSTRAINT [FK_ClubUser_Club]
    GO

    DROP TABLE [dbo].[ClubUsers]
    GO

    DROP TABLE [dbo].[Clubs]
    GO

    DROP TABLE [dbo].[Users]
    GO

    CREATE TABLE [dbo].[Clubs](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_Club] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[Users](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[ClubUsers](
    [ClubId] [int] NOT NULL,
    [Id] [int] NOT NULL,
    [Extra] [varchar](50) NOT NULL,
    CONSTRAINT [PK_ClubUser] PRIMARY KEY CLUSTERED
    (
    [ClubId] ASC,
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_Club] FOREIGN KEY([ClubId])
    REFERENCES [dbo].[Clubs] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_Club]
    GO

    ALTER TABLE [dbo].[ClubUsers] WITH CHECK ADD CONSTRAINT [FK_ClubUser_User] FOREIGN KEY([Id])
    REFERENCES [dbo].[Users] ([Id])
    GO

    ALTER TABLE [dbo].[ClubUsers] CHECK CONSTRAINT [FK_ClubUser_User]
    GO

    INSERT Clubs(Name)
    VALUES ('GlenEagles');

    INSERT Clubs(Name)
    VALUES ('StAndrews');

    INSERT Clubs(Name)
    VALUES ('Wentworth');

    INSERT dbo.[Users](Name)
    VALUES ('Pete');

    INSERT dbo.[Users](Name)
    VALUES ('Dave');

    INSERT ClubUsers(ClubId, Id, Extra)
    VALUES (1,1, 'Hello');






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 3 at 10:44









    PhilSPhilS

    56425




    56425













    • As on domain using Soft-Delete approach .. we could not do the Hard-Delete and then Create approach. It's quite interesting ... if we do this at the database level (see UPDATE - 1), it worked well BUT not the code level.

      – dcpartners
      Jan 3 at 20:37











    • That was mwhat I suspectedwhen I mentioned 'actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete'. In that case you would change tthe original to mark it as deleted (setting the IsDeleted flag) and create a new one cloned from the original. Does that satisfy your domain or must you update the existing record?

      – PhilS
      Jan 4 at 11:05





















    • As on domain using Soft-Delete approach .. we could not do the Hard-Delete and then Create approach. It's quite interesting ... if we do this at the database level (see UPDATE - 1), it worked well BUT not the code level.

      – dcpartners
      Jan 3 at 20:37











    • That was mwhat I suspectedwhen I mentioned 'actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete'. In that case you would change tthe original to mark it as deleted (setting the IsDeleted flag) and create a new one cloned from the original. Does that satisfy your domain or must you update the existing record?

      – PhilS
      Jan 4 at 11:05



















    As on domain using Soft-Delete approach .. we could not do the Hard-Delete and then Create approach. It's quite interesting ... if we do this at the database level (see UPDATE - 1), it worked well BUT not the code level.

    – dcpartners
    Jan 3 at 20:37





    As on domain using Soft-Delete approach .. we could not do the Hard-Delete and then Create approach. It's quite interesting ... if we do this at the database level (see UPDATE - 1), it worked well BUT not the code level.

    – dcpartners
    Jan 3 at 20:37













    That was mwhat I suspectedwhen I mentioned 'actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete'. In that case you would change tthe original to mark it as deleted (setting the IsDeleted flag) and create a new one cloned from the original. Does that satisfy your domain or must you update the existing record?

    – PhilS
    Jan 4 at 11:05







    That was mwhat I suspectedwhen I mentioned 'actually it probably means an Update of the IsDeleted field as opposed to actually doing a Delete'. In that case you would change tthe original to mark it as deleted (setting the IsDeleted flag) and create a new one cloned from the original. Does that satisfy your domain or must you update the existing record?

    – PhilS
    Jan 4 at 11:05















    2














    * THIS DOES NOT WORK - see comment *



    My third option which is the quickest for you to implement however i am not sure about all the implications.



    If you change OnModelCreating to set an index instead of a key



    i.e.



            builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });


    becomes



            builder.Entity<ClubUser>()
    .HasIndex(cu => new { cu.ClubID, cu.Id });


    The update will now work but then you do not have a key on the ClubUser which may cause other problems.






    share|improve this answer


























    • I now understand this better, without setting the key it is now implicitely making the Id field the key (i.e. the User Id) due to the name of the property - if it had been called UserId instead you would have got an error when instanciating the context that there was no primary key.

      – PhilS
      Jan 4 at 12:26











    • The implication of this is that you cannot change the User as it changes the Id property, only the Club and if you have a User with more than one club it will update all of them in the database which is bad.

      – PhilS
      Jan 4 at 12:29
















    2














    * THIS DOES NOT WORK - see comment *



    My third option which is the quickest for you to implement however i am not sure about all the implications.



    If you change OnModelCreating to set an index instead of a key



    i.e.



            builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });


    becomes



            builder.Entity<ClubUser>()
    .HasIndex(cu => new { cu.ClubID, cu.Id });


    The update will now work but then you do not have a key on the ClubUser which may cause other problems.






    share|improve this answer


























    • I now understand this better, without setting the key it is now implicitely making the Id field the key (i.e. the User Id) due to the name of the property - if it had been called UserId instead you would have got an error when instanciating the context that there was no primary key.

      – PhilS
      Jan 4 at 12:26











    • The implication of this is that you cannot change the User as it changes the Id property, only the Club and if you have a User with more than one club it will update all of them in the database which is bad.

      – PhilS
      Jan 4 at 12:29














    2












    2








    2







    * THIS DOES NOT WORK - see comment *



    My third option which is the quickest for you to implement however i am not sure about all the implications.



    If you change OnModelCreating to set an index instead of a key



    i.e.



            builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });


    becomes



            builder.Entity<ClubUser>()
    .HasIndex(cu => new { cu.ClubID, cu.Id });


    The update will now work but then you do not have a key on the ClubUser which may cause other problems.






    share|improve this answer















    * THIS DOES NOT WORK - see comment *



    My third option which is the quickest for you to implement however i am not sure about all the implications.



    If you change OnModelCreating to set an index instead of a key



    i.e.



            builder.Entity<ClubUser>()
    .HasKey(cu => new { cu.ClubID, cu.Id });


    becomes



            builder.Entity<ClubUser>()
    .HasIndex(cu => new { cu.ClubID, cu.Id });


    The update will now work but then you do not have a key on the ClubUser which may cause other problems.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 4 at 12:24

























    answered Jan 3 at 10:52









    PhilSPhilS

    56425




    56425













    • I now understand this better, without setting the key it is now implicitely making the Id field the key (i.e. the User Id) due to the name of the property - if it had been called UserId instead you would have got an error when instanciating the context that there was no primary key.

      – PhilS
      Jan 4 at 12:26











    • The implication of this is that you cannot change the User as it changes the Id property, only the Club and if you have a User with more than one club it will update all of them in the database which is bad.

      – PhilS
      Jan 4 at 12:29



















    • I now understand this better, without setting the key it is now implicitely making the Id field the key (i.e. the User Id) due to the name of the property - if it had been called UserId instead you would have got an error when instanciating the context that there was no primary key.

      – PhilS
      Jan 4 at 12:26











    • The implication of this is that you cannot change the User as it changes the Id property, only the Club and if you have a User with more than one club it will update all of them in the database which is bad.

      – PhilS
      Jan 4 at 12:29

















    I now understand this better, without setting the key it is now implicitely making the Id field the key (i.e. the User Id) due to the name of the property - if it had been called UserId instead you would have got an error when instanciating the context that there was no primary key.

    – PhilS
    Jan 4 at 12:26





    I now understand this better, without setting the key it is now implicitely making the Id field the key (i.e. the User Id) due to the name of the property - if it had been called UserId instead you would have got an error when instanciating the context that there was no primary key.

    – PhilS
    Jan 4 at 12:26













    The implication of this is that you cannot change the User as it changes the Id property, only the Club and if you have a User with more than one club it will update all of them in the database which is bad.

    – PhilS
    Jan 4 at 12:29





    The implication of this is that you cannot change the User as it changes the Id property, only the Club and if you have a User with more than one club it will update all of them in the database which is bad.

    – PhilS
    Jan 4 at 12:29











    2














    About:




    InvalidOperationException: The property 'ClubID' on entity type
    'ClubApplicationUser' is part of a key...




    PrimaryKey in ClubApplicationUsers table is both ClubID and Id.
    You can't just make changes to existing records by Id.



    For example this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString());


    Must be like this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString());


    Or:



    var clubApplicationUsersToUpdate = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();


    About:




    2nd approach:

    ...

    Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.




    I'll explain with example:



    Clubs: 1, 2, 3
    ApplicationUsers: A, B, C
    ClubApplicationUser: A1, A2


    Trying to remove A1, and add A2 - it says A2 already exists.



    Solution is closer to the 2nd approach:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    //delete all club memberships and add new one
    var clubApplicatonUsersToRemove = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();

    foreach (var clubApplicatonUser in clubApplicatonUsersToRemove)
    {
    _context.ClubApplicationUser.Remove(clubApplicatonUser);
    }

    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();

    return Page();
    }


    If you don't want to delete anything, but just add new record:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    // dont delete, just add new one
    var clubApplicatonUserExists = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID).FirstOrDefaultAsync();


    if (clubApplicatonUserExists == null)
    {
    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();
    }

    return Page();
    }





    share|improve this answer


























    • With this approach - "don't want to delete anything, but just add new record" ... how do we differentiate this then when we get the list for instance (.FirstOrDefaultAsync)?

      – dcpartners
      Jan 8 at 21:23













    • With this approach - "Solution is closer to the 2nd approach:" above, we have a soft-deleted approach that we want to keep the record and this might work.

      – dcpartners
      Jan 8 at 21:36











    • I din't get exactly what you need to achieve. My examples are just to explain the problem and provide working example code. You can toon it to work for you, or provide exactly what you need to delete and what to keep/create.

      – Obelixx
      Jan 9 at 7:43











    • Sorry for the late reply. I did what you suggest in term of : var clubApplicationUserToUpdate = await _context.ClubApplicationUser .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString()); but in this case SelectedClubID we changed to originalClubID ... but when we save still have the same issue?

      – dcpartners
      Jan 11 at 20:42











    • What is the primary goal? (delete all club relations to user or delete one club related to user, and then what - add selected if it dosen't exist) How you get the ClubId that needs to be deleted?

      – Obelixx
      Jan 15 at 11:36
















    2














    About:




    InvalidOperationException: The property 'ClubID' on entity type
    'ClubApplicationUser' is part of a key...




    PrimaryKey in ClubApplicationUsers table is both ClubID and Id.
    You can't just make changes to existing records by Id.



    For example this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString());


    Must be like this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString());


    Or:



    var clubApplicationUsersToUpdate = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();


    About:




    2nd approach:

    ...

    Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.




    I'll explain with example:



    Clubs: 1, 2, 3
    ApplicationUsers: A, B, C
    ClubApplicationUser: A1, A2


    Trying to remove A1, and add A2 - it says A2 already exists.



    Solution is closer to the 2nd approach:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    //delete all club memberships and add new one
    var clubApplicatonUsersToRemove = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();

    foreach (var clubApplicatonUser in clubApplicatonUsersToRemove)
    {
    _context.ClubApplicationUser.Remove(clubApplicatonUser);
    }

    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();

    return Page();
    }


    If you don't want to delete anything, but just add new record:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    // dont delete, just add new one
    var clubApplicatonUserExists = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID).FirstOrDefaultAsync();


    if (clubApplicatonUserExists == null)
    {
    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();
    }

    return Page();
    }





    share|improve this answer


























    • With this approach - "don't want to delete anything, but just add new record" ... how do we differentiate this then when we get the list for instance (.FirstOrDefaultAsync)?

      – dcpartners
      Jan 8 at 21:23













    • With this approach - "Solution is closer to the 2nd approach:" above, we have a soft-deleted approach that we want to keep the record and this might work.

      – dcpartners
      Jan 8 at 21:36











    • I din't get exactly what you need to achieve. My examples are just to explain the problem and provide working example code. You can toon it to work for you, or provide exactly what you need to delete and what to keep/create.

      – Obelixx
      Jan 9 at 7:43











    • Sorry for the late reply. I did what you suggest in term of : var clubApplicationUserToUpdate = await _context.ClubApplicationUser .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString()); but in this case SelectedClubID we changed to originalClubID ... but when we save still have the same issue?

      – dcpartners
      Jan 11 at 20:42











    • What is the primary goal? (delete all club relations to user or delete one club related to user, and then what - add selected if it dosen't exist) How you get the ClubId that needs to be deleted?

      – Obelixx
      Jan 15 at 11:36














    2












    2








    2







    About:




    InvalidOperationException: The property 'ClubID' on entity type
    'ClubApplicationUser' is part of a key...




    PrimaryKey in ClubApplicationUsers table is both ClubID and Id.
    You can't just make changes to existing records by Id.



    For example this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString());


    Must be like this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString());


    Or:



    var clubApplicationUsersToUpdate = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();


    About:




    2nd approach:

    ...

    Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.




    I'll explain with example:



    Clubs: 1, 2, 3
    ApplicationUsers: A, B, C
    ClubApplicationUser: A1, A2


    Trying to remove A1, and add A2 - it says A2 already exists.



    Solution is closer to the 2nd approach:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    //delete all club memberships and add new one
    var clubApplicatonUsersToRemove = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();

    foreach (var clubApplicatonUser in clubApplicatonUsersToRemove)
    {
    _context.ClubApplicationUser.Remove(clubApplicatonUser);
    }

    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();

    return Page();
    }


    If you don't want to delete anything, but just add new record:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    // dont delete, just add new one
    var clubApplicatonUserExists = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID).FirstOrDefaultAsync();


    if (clubApplicatonUserExists == null)
    {
    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();
    }

    return Page();
    }





    share|improve this answer















    About:




    InvalidOperationException: The property 'ClubID' on entity type
    'ClubApplicationUser' is part of a key...




    PrimaryKey in ClubApplicationUsers table is both ClubID and Id.
    You can't just make changes to existing records by Id.



    For example this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString());


    Must be like this:



    var clubApplicationUserToUpdate = await _context.ClubApplicationUser
    .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString());


    Or:



    var clubApplicationUsersToUpdate = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();


    About:




    2nd approach:

    ...

    Result: Violation of PRIMARY KEY constraint 'PK_ClubApplicationUser'.




    I'll explain with example:



    Clubs: 1, 2, 3
    ApplicationUsers: A, B, C
    ClubApplicationUser: A1, A2


    Trying to remove A1, and add A2 - it says A2 already exists.



    Solution is closer to the 2nd approach:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    //delete all club memberships and add new one
    var clubApplicatonUsersToRemove = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString()).ToList();

    foreach (var clubApplicatonUser in clubApplicatonUsersToRemove)
    {
    _context.ClubApplicationUser.Remove(clubApplicatonUser);
    }

    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();

    return Page();
    }


    If you don't want to delete anything, but just add new record:



    public async Task<IActionResult> OnPostAsync(Guid id)
    {
    if (!this.ModelState.IsValid)
    {
    return Page();
    }

    // dont delete, just add new one
    var clubApplicatonUserExists = await _context.ClubApplicationUser
    .Where(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID).FirstOrDefaultAsync();


    if (clubApplicatonUserExists == null)
    {
    _context.ClubApplicationUser.Add(new ClubApplicationUser()
    {
    Id = id.ToString(),
    ClubID = AssignClubUser.SelectedClubID
    });

    await _context.SaveChangesAsync();
    }

    return Page();
    }






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 8 at 12:31

























    answered Jan 8 at 12:26









    ObelixxObelixx

    1015




    1015













    • With this approach - "don't want to delete anything, but just add new record" ... how do we differentiate this then when we get the list for instance (.FirstOrDefaultAsync)?

      – dcpartners
      Jan 8 at 21:23













    • With this approach - "Solution is closer to the 2nd approach:" above, we have a soft-deleted approach that we want to keep the record and this might work.

      – dcpartners
      Jan 8 at 21:36











    • I din't get exactly what you need to achieve. My examples are just to explain the problem and provide working example code. You can toon it to work for you, or provide exactly what you need to delete and what to keep/create.

      – Obelixx
      Jan 9 at 7:43











    • Sorry for the late reply. I did what you suggest in term of : var clubApplicationUserToUpdate = await _context.ClubApplicationUser .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString()); but in this case SelectedClubID we changed to originalClubID ... but when we save still have the same issue?

      – dcpartners
      Jan 11 at 20:42











    • What is the primary goal? (delete all club relations to user or delete one club related to user, and then what - add selected if it dosen't exist) How you get the ClubId that needs to be deleted?

      – Obelixx
      Jan 15 at 11:36



















    • With this approach - "don't want to delete anything, but just add new record" ... how do we differentiate this then when we get the list for instance (.FirstOrDefaultAsync)?

      – dcpartners
      Jan 8 at 21:23













    • With this approach - "Solution is closer to the 2nd approach:" above, we have a soft-deleted approach that we want to keep the record and this might work.

      – dcpartners
      Jan 8 at 21:36











    • I din't get exactly what you need to achieve. My examples are just to explain the problem and provide working example code. You can toon it to work for you, or provide exactly what you need to delete and what to keep/create.

      – Obelixx
      Jan 9 at 7:43











    • Sorry for the late reply. I did what you suggest in term of : var clubApplicationUserToUpdate = await _context.ClubApplicationUser .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString()); but in this case SelectedClubID we changed to originalClubID ... but when we save still have the same issue?

      – dcpartners
      Jan 11 at 20:42











    • What is the primary goal? (delete all club relations to user or delete one club related to user, and then what - add selected if it dosen't exist) How you get the ClubId that needs to be deleted?

      – Obelixx
      Jan 15 at 11:36

















    With this approach - "don't want to delete anything, but just add new record" ... how do we differentiate this then when we get the list for instance (.FirstOrDefaultAsync)?

    – dcpartners
    Jan 8 at 21:23







    With this approach - "don't want to delete anything, but just add new record" ... how do we differentiate this then when we get the list for instance (.FirstOrDefaultAsync)?

    – dcpartners
    Jan 8 at 21:23















    With this approach - "Solution is closer to the 2nd approach:" above, we have a soft-deleted approach that we want to keep the record and this might work.

    – dcpartners
    Jan 8 at 21:36





    With this approach - "Solution is closer to the 2nd approach:" above, we have a soft-deleted approach that we want to keep the record and this might work.

    – dcpartners
    Jan 8 at 21:36













    I din't get exactly what you need to achieve. My examples are just to explain the problem and provide working example code. You can toon it to work for you, or provide exactly what you need to delete and what to keep/create.

    – Obelixx
    Jan 9 at 7:43





    I din't get exactly what you need to achieve. My examples are just to explain the problem and provide working example code. You can toon it to work for you, or provide exactly what you need to delete and what to keep/create.

    – Obelixx
    Jan 9 at 7:43













    Sorry for the late reply. I did what you suggest in term of : var clubApplicationUserToUpdate = await _context.ClubApplicationUser .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString()); but in this case SelectedClubID we changed to originalClubID ... but when we save still have the same issue?

    – dcpartners
    Jan 11 at 20:42





    Sorry for the late reply. I did what you suggest in term of : var clubApplicationUserToUpdate = await _context.ClubApplicationUser .FirstOrDefaultAsync(m => m.Id == id.ToString() && m.ClubID == AssignClubUser.SelectedClubID.ToString()); but in this case SelectedClubID we changed to originalClubID ... but when we save still have the same issue?

    – dcpartners
    Jan 11 at 20:42













    What is the primary goal? (delete all club relations to user or delete one club related to user, and then what - add selected if it dosen't exist) How you get the ClubId that needs to be deleted?

    – Obelixx
    Jan 15 at 11:36





    What is the primary goal? (delete all club relations to user or delete one club related to user, and then what - add selected if it dosen't exist) How you get the ClubId that needs to be deleted?

    – Obelixx
    Jan 15 at 11:36











    1














    Another solution if you have control of the database schema is to add a surragate key to the link table.



    Then if you need to update the club or user you are not changing the entity unique identifier and hence it will be allowed.






    share|improve this answer




























      1














      Another solution if you have control of the database schema is to add a surragate key to the link table.



      Then if you need to update the club or user you are not changing the entity unique identifier and hence it will be allowed.






      share|improve this answer


























        1












        1








        1







        Another solution if you have control of the database schema is to add a surragate key to the link table.



        Then if you need to update the club or user you are not changing the entity unique identifier and hence it will be allowed.






        share|improve this answer













        Another solution if you have control of the database schema is to add a surragate key to the link table.



        Then if you need to update the club or user you are not changing the entity unique identifier and hence it will be allowed.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 3 at 10:47









        PhilSPhilS

        56425




        56425






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53986919%2fneed-a-help-to-update-the-model%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith