Entity Framework 6 Code Первое отображение функции

c# ef-code-first entity-framework entity-framework-6 sql-function

Вопрос

Я хочу интегрировать Entity Framework 6 в нашу систему, но имею проблему.

  1. Я хочу использовать Code First. Я не хочу использовать файл Database First * .edmx по другим причинам.
  2. Я использую сопоставление атрибутов [Таблица], [Столбец], и это отлично работает
  3. База данных имеет множество пользовательских функций, и мне нужно использовать их в запросе Linq To Entities.

Проблема заключается в следующем:

Я не могу сопоставить функцию с помощью атрибута, например [Таблица], [Колонка]. Доступен только 1 атрибут [DbFunction], для которого требуется * .edmx-файл.

Я имею возможность отображать функции в файле * .edmx, но это означает, что я не могу использовать сопоставление атрибутов для объектов: [Таблица], [Столбец]. Сопоставление должно быть заполнено в * .edmx или в атрибутах.

Я попытался создать DbModel и добавить функцию через этот код:

public static class Functions
{
    [DbFunction("CodeFirstNamespace", "TestEntity")]
    public static string TestEntity()
    {
        throw new NotSupportedException();
    }
}


public class MyContext : DbContext, IDataAccess
{
    protected MyContext (string connectionString)
        : base(connectionString, CreateModel())
    {
    }

    private static DbCompiledModel CreateModel()
    {
        var dbModelBuilder = new DbModelBuilder(DbModelBuilderVersion.Latest);
        dbModelBuilder.Entity<Warehouse>();
        var dbModel = dbModelBuilder.Build(new DbProviderInfo("System.Data.SqlClient", "2008"));

        var edmType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String);
        var payload =
            new EdmFunctionPayload
            {
                Schema = "dbo",
                ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
                IsComposable = true,
                IsNiladic = false,
                IsBuiltIn = false,
                IsAggregate = false,
                IsFromProviderManifest = true,
                StoreFunctionName = "TestEntity",
                ReturnParameters =
                    new[]
                    {
                        FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue)
                    }
            };

        var function = EdmFunction.Create("TestEntity", "CodeFirst", DataSpace.CSpace, payload, null);
        dbModel.DatabaseMapping.Model.AddItem(function);
        var compiledModel = dbModel.Compile();       // Error happens here
        return compiledModel;
    }
}

Но имеют исключение:

Во время генерации модели были обнаружены одна или несколько ошибок проверки:

Edm.String: : The namespace 'String' is a system namespace and cannot be used by other schemas. Choose another namespace name.

Проблема заключается в переменной «edmType». Я не могу правильно создать ReturnType для функции. Может ли кто-нибудь предложить, как я могу добавить функцию в модель? Интерфейс функции добавления раскрывается, поэтому он должен быть в состоянии сделать, но в этой ситуации нет информации в Интернете. Вероятно, кто-то знает, когда команда Entity Framework собирается реализовать сопоставление атрибутов для таких функций, как Line To Sql.

Версия EF: 6.0.0-beta1-20521

Благодаря!


Да, это работает для меня. Но только для скалярных функций. Мне также нужна функция отображения, которая возвращает IQueryable:

 IQueryable<T> MyFunction()

Где T - EntityType или RowType или любой тип. Я не могу этого сделать вообще (версия EF 6.0.2-21211). Я думаю, что это должно работать следующим образом:

private static void RegisterEdmFunctions(DbModel model)
{
    var storeModel = model.GetStoreModel();
    var functionReturnValueType = storeModel.EntityTypes.Single(arg => arg.Name == "MyEntity").GetCollectionType();
    var payload =
        new EdmFunctionPayload
        {
            IsComposable = true,
            Schema = "dbo",
            StoreFunctionName = "MyFunctionName",
            ReturnParameters =
                new[]
                { 
                    FunctionParameter.Create("ReturnValue", functionReturnValueType, ParameterMode.ReturnValue)
                },
            Parameters =
                new[]
                {
                    FunctionParameter.Create("MyFunctionInputParameter", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), ParameterMode.In)
                }
        };
    storeModel.AddItem(EdmFunction.Create(
        payload.StoreFunctionName,
        "MyFunctionsNamespace",
        DataSpace.SSpace,
        payload,
        payload.Parameters.Select(arg => MetadataProperty.Create(arg.Name, arg.TypeUsage, null)).ToArray()));
}

Но все равно не повезло:

  model.Compile();  // ERROR 

Возможно ли это или нет? Возможно, шаги неправильные? Вероятно, поддержка будет добавлена ​​в EF 6.1. Любая информация будет очень полезна.

Благодаря!

Популярные ответы

Пока не пробовал, но Entity Framework 6.1 включает API общедоступного отображения . Moozzyk реализовала функции Store для EntityFramework CodeFirst, используя эту новую функциональность.

Вот как выглядит код:

public class MyContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(new FunctionsConvention<MyContext>("dbo"));
    }

    [DbFunction("MyContext", "CustomersByZipCode")]
    public IQueryable<Customer> CustomersByZipCode(string zipCode)
    {
        var zipCodeParameter = zipCode != null ?
            new ObjectParameter("ZipCode", zipCode) :
            new ObjectParameter("ZipCode", typeof(string));

        return ((IObjectContextAdapter)this).ObjectContext
            .CreateQuery<Customer>(
                string.Format("[{0}].{1}", GetType().Name, 
                    "[CustomersByZipCode](@ZipCode)"), zipCodeParameter);
    }

    public ObjectResult<Customer> GetCustomersByName(string name)
    {
        var nameParameter = name != null ?
            new ObjectParameter("Name", name) :
            new ObjectParameter("Name", typeof(string));

        return ((IObjectContextAdapter)this).ObjectContext.
            ExecuteFunction("GetCustomersByName", nameParameter);
    }
}



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему