我试图根据子查询计算布尔字段
var dtfs = cntx.Set<Models.DocTypeField>()
.Include(dtf => dtf.Field)
.Where(dtf => dtf.DocTypeId == docTypeId)
.Select(dtf => new
{
DocTypeField = dtf,
HasData = (cntx.Set<Models.DocumentData>()
.Any(dd => dd.DocTypeId == dtf.DocTypeId
&& dd.DataValues.Any(ddv => ddv.FieldId == dtf.FieldId)))
});
DocTypeField
和DocumentData
之间没有导航属性(或可遍历路径)。当我运行上面的查询时,我得到以下异常:
测试方法
Core.Sebring.DataAccess.Ef.Test.EF_DocTypeDALTest.EF_DocTypeDALTest_GetDocTypeIndexes
threw exception:
System.NotSupportedException:
LINQ to Entities does not recognize the method
'System.Data.Entity.DbSet`1[Core.Sebring.Models.DocumentData]
Set[DocumentData]()' method, and this method cannot be translated
into a store expression.
是否有linq to entity方式来完成上述查询?如果可能的话,我宁愿不在DocTypeField
和DocumentData
之间添加导航属性(或可遍历的路径)。
* 更新1 * 作为我做的工作
class FieldDocTypeField
{
public int DocTypeFieldId { get; set; }
public int DocTypeId { get; set; }
public int FieldDataType { get; set; }
public int FieldId { get; set; }
public byte[] LastChanged { get; set; }
public bool Required { get; set; }
public string FieldName { get; set; }
public bool HasData { get; set; }
}
var dtfs = cntx.DbContext.Database.SqlQuery<FieldDocTypeField>(@"select dtf.*,f.*,
HasData = (CASE WHEN EXISTS(Select DocumentDataValue.FieldId
from DocumentData
inner join DocumentDataValue on DocumentData.DocumentDataId=DocumentDataValue.DocumentDataId
where DocumentData.DocTypeId = @DocTypeId AND dtf.FieldId = 1) THEN cast(1 as bit) ELSE cast(0 as bit) END)
from DocTypeField dtf
inner join Field f on dtf.FieldId = f.FieldId WHERE dtf.DocTypeId=@DocTypeId", new System.Data.SqlClient.SqlParameter("@DocTypeId", docTypeId));
foreach (var dtf in dtfs)
{
docTypeFields.Add(new Models.DocTypeField
{
DocTypeFieldId = dtf.DocTypeFieldId,
DocTypeId = dtf.DocTypeId,
FieldDataType = dtf.FieldDataType,
FieldId = dtf.FieldId,
LastChanged = dtf.LastChanged,
Required = dtf.Required,
FieldName = dtf.FieldName,
HasData = dtf.HasData
});
}
它不太好但是它可以工作并完成同样的事情。在DocTypeField
和DocumentData
实体之间没有添加导航属性的情况下,我找不到使用linq到实体执行上述操作的方法。
答案 0 :(得分:0)
您可以先将数据提取到内存中,然后再进行第二次select
。
var dtfs = cntx.Set<Models.DocTypeField>()
.Include(dtf => dtf.Field)
.Where(dtf => dtf.DocTypeId == docTypeId)
.ToList() // pull the data to memory and then the following select can execute successfully.
.Select(dtf => new
{
DocTypeField = dtf,
HasData = (cntx.Set<Models.DocumentData>()
.Any(dd => dd.DocTypeId == dtf.DocTypeId
&& dd.DataValues.Any(ddv => ddv.FieldId == dtf.FieldId)))
});