Подтвердить что ты не робот

Поддержка табличных функций в коде EF6?

Можно ли сначала вызвать TVF в коде EF6?

Вначале я начал новый проект, используя EF6 Database, и EF смог импортировать TVF в модель и назвать ее просто отлично.

Но обновление модели стало очень трудоемким и проблематичным с большим объемом данных, доступным только для чтения, без RI, с которым я столкнулся.

Итак, я сначала попытался преобразовать в EF6-код, используя инструмент Power Tools Reverse Engineering для создания классов контекста и модели.

К сожалению, инструмент Reverse Engineering не импортировал TVF.

Далее я попытался скопировать DBFunctions из моей старой базы данных First DbContext в новый Code First DbContext, но это дало мне ошибку, что мой TVF: "не может быть разрешено в действительный тип или функцию".

Можно ли сначала создать код для Fluent для TVF?

Если нет, есть ли работа?

Я предполагаю, что я мог бы использовать SP вместо TVF, но надеялся, что могу использовать в основном TVF для работы с проблемной БД, в которой я застрял.

Спасибо за любые идеи о работе

4b9b3361

Ответ 1

Теперь это возможно. Я создал условное соглашение модели, которое позволяет использовать функции хранилища в CodeFirst в EF6.1. Соглашение доступно на NuGet http://www.nuget.org/packages/EntityFramework.CodeFirstStoreFunctions. Вот ссылка на блогпост, содержащий все подробности: http://blog.3d-logic.com/2014/04/09/support-for-store-functions-tvfs-and-stored-procs-in-entity-framework-6-1/

Ответ 2

[Испытано] с помощью:

Install-Package EntityFramework.CodeFirstStoreFunctions

Объявить класс для результата вывода:

    public class MyCustomObject
        {
            [Key]
            public int Id { get; set; }
            public int Rank { get; set; }
        }

Создайте метод в классе DbContext

[DbFunction("MyContextType", "SearchSomething")]
public virtual IQueryable<MyCustomObject> SearchSomething(string keywords)
{
   var keywordsParam = new ObjectParameter("keywords", typeof(string)) 
                           { 
                              Value = keywords 
                            };
    return (this as IObjectContextAdapter).ObjectContext
    .CreateQuery<MyCustomObject>(
     "MyContextType.SearchSomething(@keywords)", keywordsParam);
}

Добавить

public DbSet<MyCustomObject> SearchResults { get; set; }

в класс DbContext

Добавьте в метод overriden OnModelCreating:

 modelBuilder.Conventions.Add(new FunctionsConvention<MyContextType>("dbo"));

И теперь вы можете позвонить/присоединиться к значения таблицы функционируют следующим образом:

CREATE FUNCTION SearchSomething
(   
    @keywords nvarchar(4000)
)
RETURNS TABLE 
AS
RETURN 
(SELECT KEY_TBL.RANK AS Rank, Id
FROM MyTable 
LEFT JOIN freetexttable(MyTable , ([MyColumn1],[MyColumn2]), @keywords) AS KEY_TBL      
ON MyTable.Id = KEY_TBL.[KEY]  
WHERE KEY_TBL.RANK > 0   
)
GO

Ответ 3

Мне удалось получить доступ к TVF с помощью кода ниже. Это работает в EF6. Имена свойств модели должны соответствовать именам столбцов базы данных.

List<MyModel> data =
                db.Database.SqlQuery<MyModel>(
                "select * from dbo.my_function(@p1, @p2, @p3)",
                new SqlParameter("@p1", new System.DateTime(2015,1,1)),
                new SqlParameter("@p2", new System.DateTime(2015, 8, 1)),
                new SqlParameter("@p3", 12))
            .ToList();

Ответ 4

Я действительно начал изучать его в EF6.1 и что-то, что работает над ночными сборками. Проверьте this и этот вне.

Ответ 5

Я разработал библиотеку для этой функции. Вы можете просмотреть мою статью о UserTableFunctionCodeFirst. Вы можете использовать свою функцию без написания SQL-запроса.

Обновление

Прежде всего, вы должны добавить ссылку на вышеупомянутую библиотеку, а затем вам нужно создать класс параметров для вашей функции. Этот класс может содержать любое число и тип параметра

public class TestFunctionParams
    {
        [CodeFunctionAttributes.FunctionOrder(1)]
        [CodeFunctionAttributes.Name("id")]
        [CodeFunctionAttributes.ParameterType(System.Data.SqlDbType.Int)]
        public int Id { get; set; }
    }

Теперь вам нужно добавить следующее свойство в свой DbContext, чтобы вызвать функцию и отобразить ее свойство.

[CodeFunctionAttributes.Schema("dbo")] // This is optional as it is set as dbo as default if not provided.
        [CodeFunctionAttributes.Name("ufn_MyFunction")] // Name of function in database.
        [CodeFunctionAttributes.ReturnTypes(typeof(Customer))]
        public TableValueFunction<TestFunctionParams> CustomerFunction { get; set; }

Затем вы можете вызвать свою функцию, как показано ниже.

using (var db = new DataContext())
            {
                var funcParams = new TestFunctionParams() { Id = 1 };
                var entity = db.CustomerFunction.ExecuteFunction(funcParams).ToList<Customer>();
            }

Это вызовет вашу пользовательскую функцию и карту для объекта.

Ответ 6

Аналогичная вещь теперь также предоставляется пакетом EntityFramework.Functions. Этот, кажется, более современный.

Исходный код доступен на GitHub, а вводная статья объясняет основные принципы.