Integration with EFCore.NetTopologySuite
I was led to do this by #49 saying to open new if still existing
I've followed all steps in the above adding the following mappings:
Linq2Db Config
LinqToDBForEFTools.Initialize();
DataConnection.TurnTraceSwitchOn();
DataConnection.WriteTraceLine = (message, displayName, traceLevel) =>
{
Console.WriteLine($"{displayName} {message}");
};
var mapping = MappingSchema.Default;
var geoWriter = new SqlServerBytesWriter();
mapping.SetConverter<Point, DataParameter>(g =>
{
var x = geoWriter.Write(g);
return new DataParameter("p", x, DataType.Udt);
});
var reader = new SqlServerBytesReader();
mapping.SetConverter<byte[], Geometry>((sqlGeomInBytes) =>
{
var geometry = reader.Read(sqlGeomInBytes);
return geometry;
});
And I have the following code I'm trying to run:
Query
using (var dc = context.CreateLinqToDBContext())
{
await using var table = await dc.CreateTempTableAsync(
stations,
tableName: Guid.NewGuid().ToString(),
databaseName: "foo",
cancellationToken: cancellationToken);
var targetTable = dc.GetTable<StationEntity>();
var x = await targetTable.Merge()
.Using(table)
.On((tgt, src) => tgt.Location.Distance(src.Location) < 10)
.InsertWhenNotMatched(station => station)
.UpdateWhenMatched((tgt, src) => src)
.MergeAsync(cancellationToken);
}
Note: context here is my injected DbContext instance
But when executing this I get SQL Error
Stack Trace
Exception: Microsoft.Data.SqlClient.SqlException
Message : 'STDistance' is not a recognized built-in function name.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.SqlCommand.InternalEndExecuteNonQuery(IAsyncResult asyncResult, Boolean isInternal, String endMethod)
at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult)
at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(IAsyncResult asyncResult)
at Microsoft.Data.SqlClient.SqlCommand.<>c.<InternalExecuteNonQueryAsync>b__210_1(IAsyncResult result)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location ---
at LinqToDB.Data.DataConnection.ExecuteNonQueryAsync(CancellationToken cancellationToken)
at LinqToDB.Data.DataConnection.ExecuteNonQueryAsync(CancellationToken cancellationToken)
at LinqToDB.Data.DataConnection.ExecuteNonQueryDataAsync(CancellationToken cancellationToken)
at LinqToDB.Data.DataConnection.ExecuteNonQueryDataAsync(CancellationToken cancellationToken)
Which is correct, I can see ON (STDistance([Source].[Location]) < 10) given as the predicate in outputted query _(It should be [Target].[Location].STDistance([Source].[Location]) but using these operations from Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite in other more simpler queries behaves as expected
await context.Stations.Where(station <= station.Distance(somePoint) < 100)
.ToListAsync()
(I can see that issue #49 was having the exact same with another function at the end of the thread)
Just FYI I've managed to get around this for now by defining the following:
[Sql.Expression("{0}.STDistance({1})", ServerSideOnly = true)]
public static double DistanceTo(this Point p1, Point p2)
=> throw new NotImplementedException("Method cannot be executed during runtime");