Поддержка табличных функций в коде 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 для работы с проблемной БД, в которой я застрял.
Спасибо за любые идеи о работе
Ответы
Ответ 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, а вводная статья объясняет основные принципы.