我当前的数据库有一个Files表,由其他几个表引用。我想要实现的是检索一个文件列表,其中根本没有引用主键。
模型的结构如下所示。
public class File
{
public int FileId { get; set; }
public ......
}
public class AFiles
{
public int AFilesId { get; set; }
[ForeignKey("File")]
public int FileId { get; set; }
public virtual File File { get; set; }
.....
}
public class BFiles
{
public int BFilesId { get; set; }
[ForeignKey("File")]
public int FileId { get; set; }
public virtual File File { get; set; }
.....
}
我一直在尝试的是:
return context.File.Where(x =>
!context.AFiles.Any(y => y.FileId == x.FileId) &&
!context.BFiles.Any(y => y.FileId == x.FileId)
).Select(x => x.FileId).ToList();
但这会引发Unable to create a constant value of type 'AFile'. Only primitive types or enumeration types are supported in this context.
是否有一种优雅的处理方式,我不能只从AFiles和BFiles中提取完整的FileId引用列表,因为这样做太昂贵了。
答案 0 :(得分:2)
var ids = context.AFiles.Select(af => af.FileId)
.Union(context.BFiles.Select(bf => bf.FileId))
.Distinct();
var files = context.File.Where(f => !ids.Contains(f.FileId)).ToList();
试试这个
它将导致类似以下内容(SQL Server Profiler)
SELECT
[Extent1].[FileId] AS [Id],
[Extent1].[Name] AS [Name],
FROM [dbo].[File] AS [Extent1]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM ( SELECT DISTINCT
[UnionAll1].[FileId] AS [C1]
FROM (SELECT
[Extent2].[FileId] AS [FileId]
FROM [dbo].[FilesA] AS [Extent2]
UNION ALL
SELECT
[Extent3].[FileId] AS [FileId]
FROM [dbo].[FilesB] AS [Extent3]) AS [UnionAll1]
) AS [Distinct1]
WHERE [Distinct1].[C1] = [Extent1].[FileId]
)
答案 1 :(得分:1)
这是一个应该执行您想要的任务的查询。
List<int> ids;
using (var context = new Context())
{
ids = (
from f in context.Files
from a in context.AFiles
from b in context.BFiles
where a.FileId != f.FileId && b.FileId != f.FileId
select f.FileId).ToList();
}
public class File {
[Key] public int FileId { get; set; }
}
public class AFile {
[Key] public int AFileId { get; set; }
[ForeignKey("File")]
public int FileId { get; set; }
public virtual File File { get; set; }
}
public class BFile {
[Key] public int BFileId { get; set; }
[ForeignKey("File")]
public int FileId { get; set; }
public virtual File File { get; set; }
}
public class Context : DbContext {
public DbSet<File> Files { get; set; }
public DbSet<AFile> AFiles { get; set; }
public DbSet<BFile> BFiles { get; set; }
}
生成的SQL查询
SELECT
[Filter1].[FileId1] AS [FileId]
FROM (SELECT [Extent1].[FileId] AS [FileId1]
FROM [dbo].[Files] AS [Extent1]
CROSS JOIN [dbo].[AFiles] AS [Extent2]
WHERE [Extent2].[FileId] <> [Extent1].[FileId] ) AS [Filter1]
CROSS JOIN [dbo].[BFiles] AS [Extent3]
WHERE [Extent3].[FileId] <> [Filter1].[FileId1]