LinqKit 嵌套调用 "LINQ to Entities does not recognize the method 'Invoke'"
LinqKit nested invoke "LINQ to Entities does not recognize the method 'Invoke'"
我不完全理解为什么 select 中的嵌套调用在 LinqKit 中不起作用,想知道是否有人能够帮助我理解。
我的问题:
首先让我列出有效的方法。
假设我们有三个数据库对象:
public class Customer {
public int Id {get; set;}
public string Name {get; set;}
public ICollection<Address> Addresses {get;set;}
}
public class Address {
public int Id {get;set;}
public string AddressLine {get;set;}
public int? Customer_Id { get; set; }
[ForeignKey("Customer_Id")]
public virtual Customer Customer {get; set;}
public int? Coordinates_Id { get; set; }
[ForeignKey("Coordinates_Id")]
public virtual Coordinates Coordinates {get; set;}
}
public class Coordinates {
public int Id {get;set;}
public double Latitude {get;set;}
public double Longitude {get;set;}
}
而且我有三个模型
public class CustomerModel {
public int Id {get; set;}
public string Name {get;set;}
public AddressModel Address {get;set;}
}
public class AddressModel{
public int Id {get;set;}
public string AddressLine {get;set;}
public CoordinatesModel Coordinates {get;set;}
}
public class CoordinatesModel {
public int Id {get;set;}
public double Latitude {get;set;}
public double Longitude {get;set;}
}
所以,现在我想创建可重复使用的 select 表达式。所以我创造了这些
public static Expression<Func<Address, AddressModel>> ToAddressModel = address =>
new AddressModel {
Id = address.Id,
AddressLine = address.AddressLine,
Coordinates = new Coordinates {
Id = address.Coordinates.Id,
Latitude = address.Coordinates.Latitude,
Longitude = address.Coordinates.Longitude
}
};
public static Expression<Func<Customer, CustomerModel>> ToCustomerModel = customer =>
new CustomerModel {
Id = customer.Id,
Name = customer.Name
Address = customer.Addresses.AsQueryable().Select(ToAddressModel).ToList()
};
最后,如果我去查询这个,我会写
dbContext.Customers
.AsExpandable()
.Select(ToCustomerModel)
.ToList();
这按预期工作。但我现在想使 CoordinatesModel 更具可重用性,并制作一个 Expression 来映射它并在 AddressModels Expression 中调用它。
public static Expression<Func<Coordinates, CoordinatesModel>> ToCoordinates = coordinates =>
new Coordinates {
Id = coordinates.Id,
Latitude = coordinates.Latitude,
Longitude = coordinates.Longitude
}
public static Expression<Func<Address, AddressModel>> ToAddressModel = address =>
new AddressModel {
Id = address.Id,
AddressLine = address.AddressLine,
Coordinates = ToCoordinatesModel.Invoke(address.Coordinates)
};
现在如果我查询
dbContext.Customers
.AsExpandable()
.Select(ToCustomerModel)
.ToList();
它抛出
System.NotSupportedException: LINQ to Entities does not recognize the method 'CoordinatesModel Invoke[Coordinates,Model](System.Linq.Expressions.Expression`1[System.Func`2[Coordinates,CoordinatesModel]], Coordinates)' method
如果这不正确也没关系,我只是想了解为什么这是不正确的。如果我不针对集合调用(如不确定的导航属性),则嵌套调用没问题。
您必须明确告诉 linq 您正在扩展子表达式 - 就像您在 table 上使用 .AsExpandable()
一样 - 在子集中调用时,您必须扩展父级以遍历树并展开子表达式。
所以....您只需向父表达式添加一个 Expand
,在本例中为
public static Expression<Func<Customer, CustomerModel>> ToCustomerModel = customer =>
new CustomerModel {
Id = customer.Id,
Name = customer.Name
Address = customer.Addresses.AsQueryable().Select(ToAddressModel.Expand()).ToList()
};
导航属性很好,因为当您展开它的父级时,它会拉入所有子表达式以展开表达式 - 但选择(我只能假设是另一个投影)不会除非明确说明。
我不完全理解为什么 select 中的嵌套调用在 LinqKit 中不起作用,想知道是否有人能够帮助我理解。
我的问题:
首先让我列出有效的方法。
假设我们有三个数据库对象:
public class Customer {
public int Id {get; set;}
public string Name {get; set;}
public ICollection<Address> Addresses {get;set;}
}
public class Address {
public int Id {get;set;}
public string AddressLine {get;set;}
public int? Customer_Id { get; set; }
[ForeignKey("Customer_Id")]
public virtual Customer Customer {get; set;}
public int? Coordinates_Id { get; set; }
[ForeignKey("Coordinates_Id")]
public virtual Coordinates Coordinates {get; set;}
}
public class Coordinates {
public int Id {get;set;}
public double Latitude {get;set;}
public double Longitude {get;set;}
}
而且我有三个模型
public class CustomerModel {
public int Id {get; set;}
public string Name {get;set;}
public AddressModel Address {get;set;}
}
public class AddressModel{
public int Id {get;set;}
public string AddressLine {get;set;}
public CoordinatesModel Coordinates {get;set;}
}
public class CoordinatesModel {
public int Id {get;set;}
public double Latitude {get;set;}
public double Longitude {get;set;}
}
所以,现在我想创建可重复使用的 select 表达式。所以我创造了这些
public static Expression<Func<Address, AddressModel>> ToAddressModel = address =>
new AddressModel {
Id = address.Id,
AddressLine = address.AddressLine,
Coordinates = new Coordinates {
Id = address.Coordinates.Id,
Latitude = address.Coordinates.Latitude,
Longitude = address.Coordinates.Longitude
}
};
public static Expression<Func<Customer, CustomerModel>> ToCustomerModel = customer =>
new CustomerModel {
Id = customer.Id,
Name = customer.Name
Address = customer.Addresses.AsQueryable().Select(ToAddressModel).ToList()
};
最后,如果我去查询这个,我会写
dbContext.Customers
.AsExpandable()
.Select(ToCustomerModel)
.ToList();
这按预期工作。但我现在想使 CoordinatesModel 更具可重用性,并制作一个 Expression 来映射它并在 AddressModels Expression 中调用它。
public static Expression<Func<Coordinates, CoordinatesModel>> ToCoordinates = coordinates =>
new Coordinates {
Id = coordinates.Id,
Latitude = coordinates.Latitude,
Longitude = coordinates.Longitude
}
public static Expression<Func<Address, AddressModel>> ToAddressModel = address =>
new AddressModel {
Id = address.Id,
AddressLine = address.AddressLine,
Coordinates = ToCoordinatesModel.Invoke(address.Coordinates)
};
现在如果我查询
dbContext.Customers
.AsExpandable()
.Select(ToCustomerModel)
.ToList();
它抛出
System.NotSupportedException: LINQ to Entities does not recognize the method 'CoordinatesModel Invoke[Coordinates,Model](System.Linq.Expressions.Expression`1[System.Func`2[Coordinates,CoordinatesModel]], Coordinates)' method
如果这不正确也没关系,我只是想了解为什么这是不正确的。如果我不针对集合调用(如不确定的导航属性),则嵌套调用没问题。
您必须明确告诉 linq 您正在扩展子表达式 - 就像您在 table 上使用 .AsExpandable()
一样 - 在子集中调用时,您必须扩展父级以遍历树并展开子表达式。
所以....您只需向父表达式添加一个 Expand
,在本例中为
public static Expression<Func<Customer, CustomerModel>> ToCustomerModel = customer =>
new CustomerModel {
Id = customer.Id,
Name = customer.Name
Address = customer.Addresses.AsQueryable().Select(ToAddressModel.Expand()).ToList()
};
导航属性很好,因为当您展开它的父级时,它会拉入所有子表达式以展开表达式 - 但选择(我只能假设是另一个投影)不会除非明确说明。