Entity Framework Core возвращает несколько вариантов выбора - PullRequest
0 голосов
/ 30 ноября 2018

Как вернуть несколько выборок из EF Core (база данных SQL Server)?

Я попробовал следующий пример, но получил ошибку:

Невозможно сопоставление с реляционным типомнайдено для типа CLR 'Test1'

Ошибка в этой строке:

var valueBufferFactory = set
    .GetService<IRelationalValueBufferFactoryFactory>()
    .Create(new[] { typeof(T) }, null);

Вот соответствующий код:

public void Test()
{
    using (var cnn = _context.Database.GetDbConnection())
    {
        var cmm = cnn.CreateCommand();
        cmm.CommandType = System.Data.CommandType.Text;
        cmm.CommandText = "select id, name, code from dbo.Test1; select id, name, singleChoice from dbo.Test2";
        cmm.Connection = cnn;
        cnn.Open();
        using (var reader = cmm.ExecuteReader())
        {
            var answers = _context.Test1.Translate(reader);
            reader.NextResult();
            var questions = _context.Test2.Translate(reader);
        }
    }
}

public static List<T> Translate<T>(this DbSet<T> set, DbDataReader reader) where T : class
{
    var entityList = new List<T>();
    if (reader == null || reader.HasRows == false) return entityList;
    var entityType = set.GetService<Microsoft.EntityFrameworkCore.Metadata.IModel>().FindEntityType(typeof(T));
    var valueBufferParameter = Expression.Parameter(typeof(ValueBuffer));
    var entityMaterializerSource = set.GetService<IEntityMaterializerSource>();
    var valueBufferFactory = set.GetService<IRelationalValueBufferFactoryFactory>().Create(new[] { typeof(T) }, null);

    var stateManager = set.GetService<IStateManager>() as StateManager;
    Func<ValueBuffer, T> materializer = Expression
        .Lambda<Func<ValueBuffer, T>>(entityMaterializerSource.CreateMaterializeExpression(entityType, valueBufferParameter), valueBufferParameter)
        .Compile();
    stateManager.BeginTrackingQuery();
    while (reader.Read())
    {
        ValueBuffer valueBuffer = valueBufferFactory.Create(reader);
        var entity = materializer.Invoke(valueBuffer);
        var entry = stateManager.StartTrackingFromQuery(entityType, entity, valueBuffer, null);
        entityList.Add((T)entry.Entity);
    }
    return entityList;
}

1 Ответ

0 голосов
/ 30 ноября 2018

Вы используете много внутреннего содержимого EF Core, поэтому имейте в виду, что любая часть этого кода может (и, вероятно, будет) сломаться в будущих версиях EF Core (даже сейчас я получаю предупреждение о том, что метод Create)used устарел).

В любом случае, проблема заключается в том, что первым аргументом для Create является проблема - вы передаете new[] { typeof(T) } (тип объекта), в то время как он ожидает массив, содержащийТипы CLR свойств, которые должны быть сопоставлены с читателем.

Следовательно, должно работать следующее:

var valueBufferFactory = set.GetService<IRelationalValueBufferFactoryFactory>()
    .Create(entityType.GetProperties().Select(p => p.ClrType).ToArray(), null);
...