在 ignite.net 中的过滤器中加入 ICacheEntryFilter
Join in ICacheEntryFilter in filters in ignite.net
我正在尝试在 Ignite.net 中实现空间查询,这是我在一个区域中查找地理点的功能
public List<GeoPointDto> GetPointsInZone(CartesianPoint[] cartesianPoints, string zoneId)
{
List<GeoPointDto> reslt = new List<GeoPointDto>();
var scanQuery = new ScanQuery<string, GeoPoint>(new SearchPointsInArea(cartesianPoints, zoneId, cache));
IQueryCursor<ICacheEntry<string, GeoPoint>> queryCursor = cache.Query(scanQuery);
var res = queryCursor.GetAll();
foreach (ICacheEntry<string, GeoPoint> cacheEntry in res)
{
var tempPoint = new Dto.Point()
{
Latitude = cacheEntry.Value.Location.PointOnSurface.Y,
Longitude = cacheEntry.Value.Location.PointOnSurface.X
};
reslt.Add(new GeoPointDto()
{
CreateDate = cacheEntry.Value.CreateDate,
SerialNumber = "",
Point = tempPoint
});
}
return reslt;
}
如您所见,我发送了一个带有扫描查询的过滤器来启动缓存,这是它的代码
public class SearchPointsInArea : ICacheEntryFilter<string, GeoPoint>
{
private ICache<string, GeoPoint> cache;
private CartesianPoint[] BorderPoints { get; set; }
private string ZoneId { get; set; }
public SearchPointsInArea(CartesianPoint[] _borderPoints, string _zoneId, ICache<string, GeoPoint> _cache)
{
this.BorderPoints = _borderPoints;
this.ZoneId = _zoneId;
this.cache = _cache;
}
public bool Invoke(ICacheEntry<string, GeoPoint> entry)
{
CartesianPoint point = new CartesianPoint()
{
Y = entry.Value.Location.PointOnSurface.Y,
X = entry.Value.Location.PointOnSurface.X
};
if (IsInPolygon(BorderPoints, point))
{
var queryString = "select count(p.SerialNumber) from GeoPoint as p inner join " +
"Device as d on d.SerialNumber = p.SerialNumber inner join " +
"Vehicle as v on v.Id = d.VehicleId " +
"where v.ZoneId like (?) and p.SerialNumber like (?)";
IFieldsQueryCursor query = cache.Query(new SqlFieldsQuery(queryString, ZoneId, entry.Value.SerialNumber));
var res = query.GetAll().First();
if (Int32.Parse(res.ToString()) > 0)
return true;
else
return false;
}
else
{
return false;
}
}
public bool IsInPolygon(CartesianPoint[] poly, CartesianPoint point)
{
var coef = poly.Skip(1).Select((p, i) =>
(point.Y - poly[i].Y) * (p.X - poly[i].X)
- (point.X - poly[i].X) * (p.Y - poly[i].Y))
.ToList();
if (coef.Any(p => p == 0))
return true;
for (int i = 1; i < coef.Count(); i++)
{
if (coef[i] * coef[i - 1] < 0)
return false;
}
return true;
}
}
如您所见,我有 IsInPolygon 函数用于检查该区域中的点,然后还有一个 SqlFieldQuery 用于检查它们是否在该区域中(GeoPoint 对象没有 ZoneId,它们之间还有 2 个另一个对象),但是我收到这个错误
System.Runtime.Serialization.SerializationException: 'Serializing delegates is not supported on this platform.'
事实上,我需要加入我的过滤器才能实现我的目标。有什么办法吗?
您不应尝试将 ICache 传递给序列化并发送到远程。相反,你应该使用 [InstanceResource]
将远程 Ignite 实例注入你的过滤器 as shown in docs,在过滤期间请求它的缓存。
我正在尝试在 Ignite.net 中实现空间查询,这是我在一个区域中查找地理点的功能
public List<GeoPointDto> GetPointsInZone(CartesianPoint[] cartesianPoints, string zoneId)
{
List<GeoPointDto> reslt = new List<GeoPointDto>();
var scanQuery = new ScanQuery<string, GeoPoint>(new SearchPointsInArea(cartesianPoints, zoneId, cache));
IQueryCursor<ICacheEntry<string, GeoPoint>> queryCursor = cache.Query(scanQuery);
var res = queryCursor.GetAll();
foreach (ICacheEntry<string, GeoPoint> cacheEntry in res)
{
var tempPoint = new Dto.Point()
{
Latitude = cacheEntry.Value.Location.PointOnSurface.Y,
Longitude = cacheEntry.Value.Location.PointOnSurface.X
};
reslt.Add(new GeoPointDto()
{
CreateDate = cacheEntry.Value.CreateDate,
SerialNumber = "",
Point = tempPoint
});
}
return reslt;
}
如您所见,我发送了一个带有扫描查询的过滤器来启动缓存,这是它的代码
public class SearchPointsInArea : ICacheEntryFilter<string, GeoPoint>
{
private ICache<string, GeoPoint> cache;
private CartesianPoint[] BorderPoints { get; set; }
private string ZoneId { get; set; }
public SearchPointsInArea(CartesianPoint[] _borderPoints, string _zoneId, ICache<string, GeoPoint> _cache)
{
this.BorderPoints = _borderPoints;
this.ZoneId = _zoneId;
this.cache = _cache;
}
public bool Invoke(ICacheEntry<string, GeoPoint> entry)
{
CartesianPoint point = new CartesianPoint()
{
Y = entry.Value.Location.PointOnSurface.Y,
X = entry.Value.Location.PointOnSurface.X
};
if (IsInPolygon(BorderPoints, point))
{
var queryString = "select count(p.SerialNumber) from GeoPoint as p inner join " +
"Device as d on d.SerialNumber = p.SerialNumber inner join " +
"Vehicle as v on v.Id = d.VehicleId " +
"where v.ZoneId like (?) and p.SerialNumber like (?)";
IFieldsQueryCursor query = cache.Query(new SqlFieldsQuery(queryString, ZoneId, entry.Value.SerialNumber));
var res = query.GetAll().First();
if (Int32.Parse(res.ToString()) > 0)
return true;
else
return false;
}
else
{
return false;
}
}
public bool IsInPolygon(CartesianPoint[] poly, CartesianPoint point)
{
var coef = poly.Skip(1).Select((p, i) =>
(point.Y - poly[i].Y) * (p.X - poly[i].X)
- (point.X - poly[i].X) * (p.Y - poly[i].Y))
.ToList();
if (coef.Any(p => p == 0))
return true;
for (int i = 1; i < coef.Count(); i++)
{
if (coef[i] * coef[i - 1] < 0)
return false;
}
return true;
}
}
如您所见,我有 IsInPolygon 函数用于检查该区域中的点,然后还有一个 SqlFieldQuery 用于检查它们是否在该区域中(GeoPoint 对象没有 ZoneId,它们之间还有 2 个另一个对象),但是我收到这个错误
System.Runtime.Serialization.SerializationException: 'Serializing delegates is not supported on this platform.'
事实上,我需要加入我的过滤器才能实现我的目标。有什么办法吗?
您不应尝试将 ICache 传递给序列化并发送到远程。相反,你应该使用 [InstanceResource]
将远程 Ignite 实例注入你的过滤器 as shown in docs,在过滤期间请求它的缓存。