如何获取Entity Framework Core批量插入数据的自动生成ID?
问题(翻译后)
我正在使用Entity Framework Core的AddRange方法批量向数据库插入多条数据。目前我能想到的获取这些数据ID列自动生成ID的方法只有循环遍历实体并逐个查询,这看起来效率极低,我肯定遗漏了什么方法。请问获取所有新ID的正确方式是什么?我的插入代码如下:
public async Task<List<int>> UploadFile(Dictionary<IFormFile, string> files, string containerName, string connectionString) { var blobServiceClient = new BlobServiceClient(connectionString); var containerClient = blobServiceClient.GetBlobContainerClient(containerName); await containerClient.CreateIfNotExistsAsync(); var fileIDs = new List<int>(); var filesInfo = new List<SiteFile>(); foreach (KeyValuePair<IFormFile, string> file in files) { var fileName = String.Concat(file.Value, ContentTypetoFileExtention.GetValueOrDefault(file.Key.ContentType)); var blob = containerClient.GetBlobClient(fileName); await blob.SetHttpHeadersAsync(new BlobHttpHeaders { ContentType = file.Key.ContentType }); using (Stream stream = file.Key.OpenReadStream()) { await blob.UploadAsync(stream); } filesInfo.Add(new SiteFile() { ContainerName = containerName, FileName = fileName }); } await _siteDbContext.SiteFiles.AddRangeAsync(filesInfo); await _siteDbContext.SaveChangesAsync(); //Get IDs, somehow? return fileIDs; }
解决方案
直接从你创建的filesInfo集合中提取ID即可,无需额外查询数据库。
当调用SaveChangesAsync()后,EF Core会自动将数据库生成的主键值回填到对应的实体属性中——不管是单个Add还是批量AddRange操作,这个机制都生效。你只需要在SaveChangesAsync()执行完成后,遍历filesInfo集合提取ID:
// 替换注释处的代码 fileIDs = filesInfo.Select(f => f.Id).ToList();
原理说明
对于数据库生成的主键(比如SQL Server的IDENTITY列、MySQL的AUTO_INCREMENT列),EF Core在执行插入操作时,会自动从数据库获取生成的ID值,并赋值给你传入的实体对象的主键属性。这是EF Core内置的功能,完全不需要额外的查询操作,性能和效率都远高于逐个查询。
修改后的完整代码
public async Task<List<int>> UploadFile(Dictionary<IFormFile, string> files, string containerName, string connectionString) { var blobServiceClient = new BlobServiceClient(connectionString); var containerClient = blobServiceClient.GetBlobContainerClient(containerName); await containerClient.CreateIfNotExistsAsync(); var fileIDs = new List<int>(); var filesInfo = new List<SiteFile>(); foreach (KeyValuePair<IFormFile, string> file in files) { var fileName = String.Concat(file.Value, ContentTypetoFileExtention.GetValueOrDefault(file.Key.ContentType)); var blob = containerClient.GetBlobClient(fileName); await blob.SetHttpHeadersAsync(new BlobHttpHeaders { ContentType = file.Key.ContentType }); using (Stream stream = file.Key.OpenReadStream()) { await blob.UploadAsync(stream); } filesInfo.Add(new SiteFile() { ContainerName = containerName, FileName = fileName }); } await _siteDbContext.SiteFiles.AddRangeAsync(filesInfo); await _siteDbContext.SaveChangesAsync(); // 直接提取自动生成的ID fileIDs = filesInfo.Select(f => f.Id).ToList(); return fileIDs; }
内容的提问来源于stack exchange,提问作者Matthew Verstraete
相关产品推荐
相关产品推荐

