gpt4 book ai didi

.net-core - 需要帮助更新模型

转载 作者:行者123 更新时间:2023-12-02 14:53:55 25 4
gpt4 key购买 nike

我有一个名为 ClubApplicationUser 的模型,它是 ClubApplicationUser 之间的桥梁,它是 Identity User 型号:

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; }



}

在 ApplicationDBContext - OnModelCreating 中我们定义了关系:

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);

我们有一个问题,我们无法更新这个,我们有错误:

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.

这是 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.");
}

}

...和 ​​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");}
}

环境:.Net 核心 2.2 Razor 页面

更新 - 1:

如果我们通过以下方式直接在数据库上更新它:

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

我们可以更新这个没问题。所以它看起来像是 .Net 核心模型中的约束。

最佳答案

我认为最好的解决方案是您需要删除和插入而不是更新,尽管考虑到您的 ClubApplicationUser 实际上它可能意味着更新 IsDeleted 字段而不是实际执行删除。

如果您按照自己域的逻辑来考虑,我认为用户通常不会将一个俱乐部的成员身份更改为另一个俱乐部的成员,他们会离开(删除)一个俱乐部并加入(插入)另一个俱乐部。

尽管我可以想出另一个确实需要更新的域,但我认为这不是一个很好的通用论点。

以下代码显示了问题的简化版本。您可以看到测试允许插入和删除但因更新而失败

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());
}
}

初始化测试数据库:

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');

关于.net-core - 需要帮助更新模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53986919/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com