Entity framework 如何在LINQ&Entity框架中查询未映射属性
因此,我从一篇关于如何在实体框架中存储具有数组数据类型的属性的文章开始了部分讨论。我没有遵循这个答案的是,将字符串InternalData设置为private而不是public,因为如果它设置为public,我会发现它有一种代码味道,因为它还没有足够的声誉在那里发表评论 我还设法在实体框架中从此映射私有属性 当我执行CR创建时,从该实体读取,一切都进行得很顺利。但是,当我的LINQ查询有一个where子句将该属性与数组数据类型一起使用时,它表示System.NotSupportedException:'指定的类型成员在LINQ to实体中不受支持。仅支持初始值设定项、实体成员和实体导航属性。“ 如何解决这个问题?以下是相关的代码块:Entity framework 如何在LINQ&Entity框架中查询未映射属性,entity-framework,linq,Entity Framework,Linq,因此,我从一篇关于如何在实体框架中存储具有数组数据类型的属性的文章开始了部分讨论。我没有遵循这个答案的是,将字符串InternalData设置为private而不是public,因为如果它设置为public,我会发现它有一种代码味道,因为它还没有足够的声誉在那里发表评论 我还设法在实体框架中从此映射私有属性 当我执行CR创建时,从该实体读取,一切都进行得很顺利。但是,当我的LINQ查询有一个where子句将该属性与数组数据类型一起使用时,它表示System.NotSupportedExcepti
public class ReminderSettings
{
[Key]
public string UserID { get; set; }
[Column("RemindForPaymentStatus")]
private string _remindForPaymentStatusCSV { get; set; }
private Status[] _remindForPaymentStatus;
[NotMapped]
public Status[] RemindForPaymentStatus
{
get
{
return Array.ConvertAll(_remindForPaymentStatusCSV.Split(','), e => (Status)Enum.Parse(typeof(Status), e));
}
set
{
_remindForPaymentStatus = value;
_remindForPaymentStatusCSV = String.Join(",", _remindForPaymentStatus.Select(x => x.ToString()).ToArray());
}
}
public static readonly Expression<Func<ReminderSettings, string>> RemindForPaymentStatusExpression = p => p._remindForPaymentStatusCSV;
}
public enum Status
{
NotPaid = 0,
PartiallyPaid = 1,
FullyPaid = 2,
Overpaid = 3
}
protected override void OnModelCreating(DbModelBuuilder modelBuilder)
{
modelBuilder.Entity<ReminderSettings>().Property(ReminderSettings.RemindForPaymentStatusExpression);
}
//This query will cause the error
public IEnumerable<ReminderSettings> GetReminderSettingsByPaymentStatus(Status[] statusArray)
{
var query = ApplicationDbContext.ReminderSettings.Where(x => x.RemindForPaymentStatus.Intersect(statusArray).Any());
return query.ToList(); //System.NotSupportedException: 'The specified type member 'RemindForPaymentStatus' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.'
}
如果LINQ表达式访问注释为[NotMapped]的属性,则实体框架无法将其转换为SQL。如果属性的getter/setter中包含自定义C代码,它也无法转换 作为一种快速但性能可能较低的解决方法,您可以执行查询中不会导致问题的部分,然后在内存中应用其他筛选
// execute query on DB server and fetch items into memory
var reminders = dbContext.ReminderSettings.ToList();
// now that we work in-memory, LINQ does not need to translate our custom code to SQL anymore
var filtered = reminders.Where(r => r.RemindForPaymentStatus.Contains(Status.NotPaid));
如果这会导致性能问题,则必须将NotMapped属性的支持字段公开,并直接使用它
var filtered = dbContext.ReminderSettings
.Where(r => r._remindForPaymentStatusCSV.Contains(Status.NotPaid.ToString("D"));
编辑
要将多个状态作为查询参数处理,可以在循环中附加Where子句,其行为类似于AND。只要您的状态枚举值是可区分的,即如果还有状态1,则不存在状态11
var query = dbContext.ReminderSettings.Select(r => r);
foreach(var statusParam in queryParams.Status) {
var statusString = statusParam.ToString("D");
query = query.Where(r => r._remindForPaymentStatusCSV.Contains(statusString));
}
var result = query.ToArray();
谢谢你,乔治。我选择后者,因为它是可伸缩的。虽然在where子句中,我想比较status数组和status参数/输入数组。我为这件事编辑了我的问题。我试着用这个来编写where子句:但是我仍然得到一个错误。var query=ApplicationDbContext.rementersettings.Wherex=>Array.convertalx.\u emendmentforpaymentstatuscsv.Split',,e=>StatusEnum.ParsetypeofStatus,e.IntersectstatusArray.Any;返回query.ToList;您也可以在不首先具体化数据集的情况下执行此操作,前提是您的数据是良好的格式,而不是CSV,但JSON会更好: