在Entity Framework Core中,我有以下实体:
public class File {
public Int32 Id { get; set; }
public Byte[] Content { get; set; }
public String Name { get; set; }
}
我有一个我需要删除的文件ID列表:
List<Int32> ids = new List<Int32> { 4, 6, 8 }; // Ids example
如何在不加载每个文件内容属性的情况下删除3个文件?
_context.Files.Remove(??);
我不想加载每个文件Content属性,因为它的大小很大。
答案 0 :(得分:2)
如果您确定数据库中存在所有ID并且上下文不包含(不跟踪)具有相同键的其他实体,则可以使用简单的伪( stub )实体:
_context.RemoveRange(ids.Select(id => new File { Id = id }));
为避免现有ID出现问题,您可以从数据库中获取现有ID:
var existingIds = _context.Files.Where(f => ids.Contains(f.Id)).Select(f => f.Id).ToList();
_context.RemoveRange(existingIds.Select(id => new File { Id = id }));
为避免跟踪实体问题,您可以使用我对Delete loaded and unloaded objects by ID in EntityFrameworkCore的回答中的FindTracked
自定义扩展方法,并将其与上述任何内容相结合。
var existingIds = _context.Files.Where(f => ids.Contains(f.Id)).Select(f => f.Id).ToList();
_context.RemoveRange(
existingIds.Select(id => _context.FindTracked(id) ?? new File { Id = id }));
答案 1 :(得分:1)
您可以尝试EntityFramework-Plus和Database.BeginTransaction()
var db = new YourDbContext();
var dbContextTransaction = db.Database.BeginTransaction();
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2)).Delete();
//some other DB actions
db.SaveChanges();
dbContextTransaction.Commit();
通过这种方式删除与事务一起提交
答案 2 :(得分:0)
只要您可以唯一标识实体,实体跟踪就可以手动进行,而无需任何数据库调用。
here中记录了您所追求的。
var entity = new EntityModel {
Id = yourId
};
var entry = context.Entry(entity);
entry.State = EntityState.Deleted;
context.SaveChanges();
与...相同...
var entity = new EntityModel {
Id = yourId
};
var entry = context.Entry(entity);
context.Remove(entry);
context.SaveChanges();
答案 3 :(得分:-1)
根据您的 dotnet 版本安装 Z.EntityFramework.Extensions 或 Z.EntityFramework.Extensions.EFCore 包。
然后在您的查询之后使用 DeleteFromQuery() 或 DeleteFromQueryAsync() 方法。
await _dbContext.MyTable.Where(w => w.TypeId == 5).DeleteFromQueryAsync();
DeleteFromQuery 让您可以直接在数据库中执行 DELETE 语句,并在选择和加载对象的情况下提供巨大的性能改进。
性能比较:
操作数:1,000 个实体 - 2,000 个实体 - 5,000 个实体
保存更改:1,000 毫秒 - 2,000 毫秒 - 5,000 毫秒
DeleteFromQuery:1 毫秒 - 1 毫秒 - 1 毫秒