为了减少数据库中表的数量,我想使用单个表来存储多个引用表的相同类型的数据:一对多关系与单个外部表的多次关系。
public class Note
{
public int Id { get; set; }
public int TargetId { get; set; }
public TargetType TargetType { get; set; }
}
public enum TargetType
{
Article,
Order,
Task,
Ticket
}
public class Article
{
public int Id { get; set; }
public ICollection<Note> Notes { get; set; }
}
public class Order
{
public int Id { get; set; }
public ICollection<Note> Notes { get; set; }
}
public class Task
{
public int Id { get; set; }
public ICollection<Note> Notes { get; set; }
}
public class Ticket
{
public int Id { get; set; }
public ICollection<Note> Notes { get; set; }
}
首先使用代码,我尝试过 OnModelCreating:
modelBuilder.Entity<Transfer>().HasMany(x =>
x.LineItems.Where(y => y.TargetId == x.Id && y.TargetType == LineItemTarget.Transfer)).WithOne();
这会产生:
<块引用>System.ArgumentException: '表达式 'x => x.Notes.Where(y => ((y.TargetId == x.Id) AndAlso (Convert(y.TargetType, Int32) == 1))) ' 不是有效的成员访问表达式。该表达式应表示一个简单的属性或字段访问:'t => t.MyProperty'。 (参数'memberAccessExpression')'
在查询时,我尝试了基本相同的方法:
return await _dbContext.Transfers.Include(x => x.LineItems.Where(y => y.TargetId == x.Id))
.ToListAsync(cancellationToken);
产生:
<块引用>System.InvalidOperationException: The LINQ expression 'DbSet<Note>()
.Where(l => EF.Property<Nullable<int>>(EntityShaperExpression:
EntityType: Article
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
, "Id") != null && object.Equals(
objA: (object)EF.Property<Nullable<int>>(EntityShaperExpression:
EntityType: Article
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
, "Id"),
objB: (object)EF.Property<Nullable<int>>(l, "ArticleId")))
.Where(l => l.TargetId == x.Id && (int)l.TargetType == 3)'
无法翻译。以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用,显式切换到客户端评估。有关详细信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2101038。
我了解此方法建议我将结果带回应用程序并尝试进一步过滤应用程序端,因为它无法自动映射关系,因为 Note 上不存在“ArticleId”。
我还尝试使用查询过滤器,我很快了解到它与前一个选项的策略相同,只是应用于该表上的所有查询。我目前知道的最后一件事是使用原始 SQL,我似乎无法将其映射到 Note 对象,并且非常希望完全避免使用原始 SQL。
本质上,我尝试在 LINQ 中编写此 SQL 查询,使用文章和 TargetType.Article,然后对 Order、Task、Ticket 和任何其他表使用相同的方法:
SELECT * FROM Articles JOIN Notes ON Articles.Id = Notes.TargetId AND Notes.TargetType = 1
如何使用 LINQ 对数据库执行该查询?