EF Core 3 DBFunction IQueryable возвращаемый тип - PullRequest
0 голосов
/ 27 января 2020

Кто-нибудь знает, возможно ли вернуть что-либо, кроме скалярного значения, используя объявление DBFunction в EF Core?

Я переношу сайт в EFCore v3.1.1 из EF6 с SQL Server ( от. Net Framework 4.7.2 до. Net Core 3.0). Функция SQL имеет возвращаемое значение типа Table из двух столбцов. например (это упрощенная версия фактического случая):

create function [dbo].[fn_getValues] (
    @tenantId int,
    @dataItemId int
)
RETURNS @dataVals table (
        Value1 nvarchar(max),
        Value2 nvarchar(max)
    )
AS
BEGIN

...
complex function
...

END

с В модели EF6 есть объявление DBFunction, которое возвращает IQueryable, где ReturnModel является POCO (то есть не является сопоставленной сущностью таблицы ):

public class ReturnModel {
  public string Value1 {get; set;} 
  public string Value2 {get; set;}
}

с функцией DBFunction EF6, объявленной как

[DbFunction("fn_getValues")]
public virtual IQueryable<ReturnModel> fn_getValues(Nullable<int> tenantId, Nullable<int> dataItemId) {
    var tenantIdParameter = tenantId.HasValue ?
        new ObjectParameter("tenantId", tenantId) :
        new ObjectParameter("tenantId", typeof(int));

    var dataItemIdParameter = dataItemId.HasValue ?
        new ObjectParameter("dataItemId", dataItemId) :
        new ObjectParameter("dataItemId", typeof(int));

    return ((IObjectContextAdapter)this).ObjectContext
       .CreateQuery<ReturnModel>("[dbo].[fn_getValues](@tenantId, @dataItemId)", tenantId, dataItemId);
}

Но я не могу заставить это работать в EF Core 3. Я попытался объявить тип возвращаемого значения как объект без ключа и переназначил функцию DBF:

[DbFunction("fn_getValues")]
public virtual IQueryable<ReturnModel> fn_getValues(Nullable<int> tenantId, Nullable<int> dataItemId) {
    throw new NotSupportedException();
}

Вот пример того, как можно использовать в гневе:

int tenantId = <something>;
int filterItemId = <something>;

using (var db = new DBContext) {

    var query = from a in db.ParentItems
    where a.filterItem = filterItemId
    select new {
        a.Id,
        a.Name,
        ModelValues = db.fn_getValues(tenantId, a.Id)
    };

    return await query.ToListAsync(); 
}

, который всегда приводит к ошибке ...

The DbFunction 'fn_getValues' has an invalid return type 'IQueryable<ReturnModel>'. Ensure that the return type can be mapped by the current provider.

Можно ли вернуть комплексный тип из EF Core3, или мне нужно будет сделать что-то ужасное, например, объединить поля данных в одно строковое значение с разделителем и разделить их в ответе?

1 Ответ

0 голосов
/ 27 января 2020

В EF Core нет такой же поддержки TVF, но есть функция компенсации. Вы можете составить дополнительные выражения запроса LINQ с помощью необработанного SQL запроса:

var searchTerm = ".NET";

var blogs = context.Blogs
    .FromSqlInterpolated($"SELECT * FROM dbo.SearchBlogs({searchTerm})")
    .Where(b => b.Rating > 3)
    .OrderByDescending(b => b.Rating)
    .ToList();

необработанного SQL запроса - составление с помощью LINQ

.FromSqlInterpolated возвращает IQueryable<T>, который можно вернуть из fn_getValues (без атрибута DbFunctionAttribute).

...