پشتیبانی از حذف و بهروز رسانی دستهای رکوردها در EF 7.0
نویسنده: وحید نصیری
تاریخ: ۱۴۰۱/۰۹/۲۴ ۲۳:۳۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
using var dbContext = new MyDbContext(); var objectToDelete = await dbContext.Objects.FirstAsync(o => o.Id == id); dbContext.Objects.Remove(objectToDelete); await dbContext.SaveChangesAsync();
using var dbContext = new MyDbContext();
var objectToDelete = new MyObject { Id = id };
dbContext.Objects.Remove(objectToDelete);
await dbContext.SaveChangesAsync(); await dbContext.Objects.Where(x => x.Id == id).ExecuteDeleteAsync();
public class User
{
public int Id { get; set; }
public required string FirstName { get; set; }
public required string LastName { get; set; }
public virtual List<Book> Books { get; set; } = new();
public virtual Address? Address { get; set; }
}
public class Book
{
public int Id { get; set; }
public required string Type { get; set; }
public required string Name { get; set; }
public virtual User User { get; set; } = default!;
public int UserId { get; set; }
}
public class Address
{
public int Id { get; set; }
public required string Street { get; set; }
public virtual User User { get; set; } = default!;
public int UserId { get; set; }
} public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; } = default!;
public DbSet<Book> Books { get; set; } = default!;
public DbSet<Address> Addresses { get; set; } = default!;
} context.Books.Where(book => book.Name.Contains("1")).ExecuteDelete(); DELETE FROM [b] FROM [Books] AS [b] WHERE [b].[Name] LIKE N'%1%'
context.Users.Where(user => user.Id <= 500).ExecuteDelete();
DELETE FROM [u] FROM [Users] AS [u] WHERE [u].[Id] <= 500 The DELETE statement conflicted with the REFERENCE constraint "FK_Books_Users_UserId". The conflict occurred in database "EF7BulkOperations", table "dbo.Books", column 'UserId'.
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; } = default!;
public DbSet<Book> Books { get; set; } = default!;
public DbSet<Address> Addresses { get; set; } = default!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder
.Entity<User>()
.HasMany(user => user.Books)
.WithOne(book => book.User)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder
.Entity<User>()
.HasOne(user => user.Address)
.WithOne(address => address.User)
.HasForeignKey<Address>(address => address.UserId)
.OnDelete(DeleteBehavior.Cascade);
}
} context.Users.Where(user => user.Id <= 400) .ExecuteUpdate(p => p.SetProperty(user => user.LastName, user => "Updated"));
UPDATE [u] SET [u].[LastName] = N'Updated' FROM [Users] AS [u] WHERE [u].[Id] <= 400
context.Users.Where(user => user.Id <= 300)
.ExecuteUpdate(p => p.SetProperty(user => user.LastName,
user => "Updated" + user.LastName)); UPDATE [u] SET [u].[LastName] = N'Updated' + [u].[LastName] FROM [Users] AS [u] WHERE [u].[Id] <= 300
context.Users.Where(user => user.Id <= 800)
.ExecuteUpdate(p => p.SetProperty(user => user.LastName,
user => "Updated" + user.LastName)
.SetProperty(user => user.FirstName,
user => "Updated" + user.FirstName)); UPDATE [u] SET [u].[FirstName] = N'Updated' + [u].[FirstName], [u].[LastName] = N'Updated' + [u].[LastName] FROM [Users] AS [u] WHERE [u].[Id] <= 800
«فقط باید دقت داشت که چون این روش خارج از سیستم Change tracking صورت میگیرد »
یک نکتهی تکمیلی: روش استفاده از خواص راهبری، در بهروزسانیهای دستهای
در همین مثال مطلب جاری، فرض کنید موجودیت کاربر، به همراه خاصیت محاسباتی تعداد کتابها (NumberOfBooks) هم هست:
public class User
{
// ...
public virtual List<Book> Books { get; set; } = new();
public int NumberOfBooks { get; set; }
}اگر سعی کنیم این خاصیت را به صورت زیر بهروز رسانی کنیم که در آن مقدار تعداد کتابها به کمک خاصیت راهبری Books محاسبه شود:
await context.Users.Where(x=> x.Id == 1).ExecuteUpdateAsync(s => s.SetProperty(user => user.NumberOfBooks,
user => user.Books.Count()));به خطای زیر میرسیم:
... could not be translated. Additional information: Translation of member 'Books' on entity type 'User' failed. This commonly occurs when the specified member is unmapped.
عنوان میکند که این خاصیت راهبری، نگاشت نشدهاست. برای رفع این مشکل باید به صورت زیر عمل کرد:
await context.Users
.Where(user => user.Id == 1)
.Select(user => new
{
user.NumberOfBooks,
BooksCount = user.Books.Count()
})
.ExecuteUpdateAsync(s => s.SetProperty(arg => arg.NumberOfBooks, arg => arg.BooksCount));در اینجا تنها کاری که انجام شده، انجام محاسبات و نگاشتهای لازم، پیش از فراخوانی متد ExecuteUpdateAsync است.