c# - code - dbfunction entity framework



Entity Framework 6 Code First отображение функций (3)

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

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

Проблема в следующем:

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

Я в порядке, чтобы отображение функций в файле * .edmx, но это означает, что я не могу использовать отображение атрибутов для сущностей: [Table], [Column] Отображение должно быть полным в * .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-бета1-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. Любая информация будет очень полезна.

Спасибо!

https://ffff65535.com


Вот все необходимые шаги [Проверено]:

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

Добавьте в переопределенный метод OnModelCreating :

modelBuilder.Conventions
.Add(new CodeFirstStoreFunctions.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

Вы можете получить тип Store из примитивного типа с помощью вспомогательного метода:

    public static EdmType GetStorePrimitiveType(DbModel model, PrimitiveTypeKind typeKind)
    {
        return model.ProviderManifest.GetStoreType(TypeUsage.CreateDefaultTypeUsage(
            PrimitiveType.GetEdmPrimitiveType(typeKind))).EdmType;
    }

В вашем примере вам нужно изменить тип возвращаемого параметра:

var edmType = GetStorePrimitiveType(model, PrimitiveTypeKind.String);


Я нашел нужную мне помощь здесь: http://entityframework.codeplex.com/discussions/466706






sql-function