Вызов пользовательской функции SQL в запросе LINQ
мне трудно заставить это работать. Я пытаюсь выполнить поиск radius, используя следующий помощник фильтра на IQueryable. Существует набор других фильтров, которые применяются до применения RadiusSearch. Порядок не должен иметь большого значения, поскольку цель состоит в том, чтобы отложить запрос до операции ToList ().
public static IQueryable<ApiSearchCommunity> RadiusSearch(this IQueryable<ApiSearchCommunity> communities)
{
var centerLatitude = 30.421278;
var centerLongitude = -97.426261;
var radius = 25;
return communities.Select(c => new ApiSearchCommunity()
{
CommunityId = c.CommunityId,
City = c.City,
//Distance = c.GetArcDistance(centerLatitude, centerLongitude, c.Latitude, c.Longitude, radius)
});
}
могу ли я как-то написать помощник, такой как GetArcDistance, выше которого, в свою очередь, вызывает UDF на SQL? Запрос я пытаюсь создать это после
SELECT
comms.community_id,
comms.city,
comms.distance
FROM (
SELECT
c.community_id,
c.city,
dbo.udf_ArcDistance(
30.421278,-97.426261,
c.community_latitude,
c.community_longitude
) AS distance
FROM communities c) AS comms
WHERE comms.distance <= 25
ORDER BY comms.distance
2 ответов
хорошо, я думаю, что понимаю вопрос - суть в том, что вы хотите иметь возможность вызывать SQL UDF как часть вашего запроса Linq to Entities.
Это если вы используете базу данных или модель первая:
эта статья объясняет, как сделать это: http://msdn.microsoft.com/en-us/library/dd456847(против.100).аспн
чтобы подвести итог, вам сначала нужно отредактировать файл edmx в Редакторе xml, в разделе edmx: StorageModels >> Schema вам нужно указать сопоставление с вашим sql udf, например
<Function Name="SampleFunction" ReturnType="int" Schema="dbo">
<Parameter Name="Param" Mode="In" Type="int" />
</Function>
тогда вам нужно создать статическую функцию где-нибудь с атрибутом EdmFunction на нем, что-то вроде этого:
public static class ModelDefinedFunctions
{
[EdmFunction("TestDBModel.Store", "SampleFunction")]
public static int SampleFunction(int param)
{
throw new NotSupportedException("Direct calls are not supported.");
}
}
этот метод будет сопоставлен UDF во время запроса Entity framework. Первый аргумент атрибута-пространство имен store - вы можете найти его в xml-файле edmx в элементе схемы (ищите пространство имен). Второй аргумент-это имя UDF.
затем вы можете назвать это чем-то вот так:
var result = from s in context.UDFTests
select new
{
TestVal = ModelDefinedFunctions.SampleFunction(22)
};
надеюсь, что это помогает.
Если вы используете Code-First
подход, то вы не может вызов UDFs, как вы хотите (начиная с EF6) - вот доказательство и еще один. Вы ограничены только вызовом UDF как часть вашего SQL-запроса:
bool result = FooContext.CreateQuery<bool>(
"SELECT VALUE FooModel.Store.UserDefinedFunction(@someParameter) FROM {1}",
new ObjectParameter("someParameter", someParameter)
).First();
что уродливо ИМО и подвержено ошибкам.
также - это MSDN страница говорит:
процесс вызова пользовательской функции требует трех основных шагов:
- определите функцию в вашей концептуальная модель или объявить функцию в модели хранения.
что по существу означает, что вам нужно использовать Model-First
подход к вызову UDFs.