您在删除用户时依赖CascadeOnDelete。这是一个相对较慢的过程,因为对于要删除的每个用户,您的数据库管理系统都必须检查所有相关表以查看与要删除的用户是否存在关系。
先删除相关对象再删除客户会更快:
using(var dbContext = new MyDbContext(...))
{
Customer userToDelete = dbContext.Users.Where(...).FirstOrDefault();
// before deleting this user, remove all related items
var rolesToRemove = dbContext.Roles.Where(role => role.UserId == userToDelete.Id);
dbContext.Roles.RemoveRange(rolesToRemove.ToList());
var notificationsToRemove = dbContext.Notifications
.Where(notification => notification.UserId == userToDelete.Id);
dbContext.Notifications.RemoveRange(notificationsToRemove.ToList());
... // etc.
dbContext.User.Remove(userToDelete();
dbContext.SaveChanges();
}
Entity Framework 的问题是,您需要先获取项目,然后才能删除它们。
如果您需要经常删除用户,则可以通过创建存储过程来绕过此提取。
class MyDbContext : DbContext
{
public DbSet<User> Users {get; set;}
... // etc
protected override OnModelCreating(...)
{
... // fluent API, table names, column names, relations between tables, ...
this.CreateStoredProcedureRemoveUser()
}
private void CreateStoredProcedureUpdateUsageCosts(DemoContext context)
{
const string sqlText = @"Create Procedure RemoveUser @UserId int as
Begin
... // Sql code to remove UserMeetings, Roles, Groups, etc
... // Sql code to remove the user
End";
this.Database.ExecuteSqlComment(sqlText);
}
// Procedure to remove the user:
public void RemoveUser(int userId)
{
const string sqlCommandRemoveUser= @"Exec RemoveUser @UserId";
object[] commandParameters = new object[]
{
new SqlParameter(@"@UserId", userId),
};
this.Database.ExecuteSqlCommand(sqlCommandRemoveUser, commandParameters);
}
}
用法:
int userId = ...
using (var dbContext = new MyDbContext())
{
dbContext.RemoveUser(userId);
}
小心:因为过程是立即执行的,所以一旦调用了方法就不能返回。例如,如果您想要回退,在删除角色后删除组时遇到异常,请使用 DbContext.Database.BeginTranscation / EndTransaction,以恢复原始情况。