c# - 可以使用 linq2db 添加自定义列吗?
问题描述
我正在使用 linq2db 和 FluentMappingBuilder 来映射我的数据库,我想知道是否可以将自定义列映射到我的类。
这是我的查询。
SELECT p.Id,
p.Name,
p.Price,
dbo.FN_DISTANCE_HAVERSINE(a.latitude, a.longitude, 48.135538400663656, 11.551979373610068) AS Distance
FROM Product p
INNER JOIN Category c ON p.IdCategory = c.Id
INNER JOIN Store s ON p.IdStore = s.Id
INNER JOIN Address a ON s.IdAddress = a.Id
WHERE Active = 1
AND CanLoad = 1
ORDER BY distance ASC
我添加到我的产品类中,并在我的映射类中Distance
设置为不是列Property(x => x.DistanceKm).IsNotColumn();
但我不知道如何使用 linq2db 进行此查询。这是可能的?
我还尝试了另一种方法,而不是使用 Sql 函数,而是使用 linq2db 完成所有操作。并且工作正常...
IQueryable<Product> products = GetQueryable();
products = from p in products
select new Product
{
Id = p.Id,
Name = p.Name,
Price = p.Price,
DistanceKm = DistanceHelper.GetDistanceWithHaversine(productFilter.Latitude, productFilter.Longitude, p.Store.Address.Latitude, p.Store.Address.Longitude)
};
var result = await products.ToListAsync();
但如果我尝试按 订购Products
,DistanceKm
我会得到一个例外:
var result = await products.OrderByDescending(p => p.DistanceKm).ToListAsync();
例外
GetDistanceWithHaversine(value(ProductRepository+<>c__DisplayClass3_0).productFilter.Latitude, value(StoreAggregator.Api.Data.Repository.ProductRepository+<>c__DisplayClass3_0).productFilter.Longitude, p.Store.Address.Latitude, p.Store.Address.Longitude)' cannot be converted to SQL.
at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertToSql(IBuildContext context, Expression expression, Boolean unwrap, ColumnDescriptor columnDescriptor, Boolean isPureExpression)
这是 linq2db 的限制,还是我可以使用其中一种方法?
编辑
我的 GetDistanceWithHaversine
实现。
该dbo.FN_DISTANCE_HAVERSINE
功能完全相同,但在 sql server 上。
public static double GetDistanceWithHaversine(double lat1, double lng1, double lat2, double lng2)
{
var R = 6371; // Radius of the earth in km
var dLat = Deg2rad(lat2 - lat1); // deg2rad below
var dLon = Deg2rad(lng2 - lng1);
var a =
Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
Math.Cos(Deg2rad(lat1)) * Math.Cos(Deg2rad(lat2)) *
Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
var d = R * c; // Distance in km
return d;
}
private static double Deg2rad(double deg)
{
return deg * ((Math.PI) / 180);
}
解决方案
解决方法很简单。你必须告诉linq2db
这个函数有数据库模拟。对于你的情况是Sql.FunctionAttribute
[Sql.Function("dbo.FN_DISTANCE_HAVERSINE")]
public static double GetDistanceWithHaversine(double lat1, double lng1, double lat2, double lng2)
{
var R = 6371; // Radius of the earth in km
var dLat = Deg2rad(lat2 - lat1); // deg2rad below
var dLon = Deg2rad(lng2 - lng1);
var a =
Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
Math.Cos(Deg2rad(lat1)) * Math.Cos(Deg2rad(lat2)) *
Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
var d = R * c; // Distance in km
return d;
}
推荐阅读
- tensorflow - 在 Keras、Tensorflow 中加载训练数据
- java - 致命异常:java.lang.NoSuchMethodError:没有虚拟方法 callEngineReleaseConnection(Lcom/squareup/okhttp/Call;)
- android - Fragment 类无法访问 Kotlin 中布局文件内的组件
- python - 如何在训练/测试拆分中使用不同的数据帧
- vba - CATIAV5 汇编或反汇编一个 catvba 项目进行版本控制
- javascript - 如何在 y 轴上偏移 Material-UI Popper(popper.js 库)位置?
- netbeans-8 - JavaFX 持久层 - 删除检索()和持久()并添加带有数据文件的 CRUD 应用程序
- python - ocr引擎返回时如何更正包含无关引号的不正确json?
- regex - 字母数字的 ElasticSearch 分析器自动完成功能
- r - 在R中将多列向下移动一行