EF4.1 - Свободный API - SqlQuery - сопоставления конфигурации при вызове sproc - Средство чтения данных несовместимо с указанным типом сущности - PullRequest
4 голосов
/ 09 июня 2011

Сценарий - унаследованное приложение с 10-летней историей, всегда использующее вызовы процедур для всего доступа к данным - нуждается в пересмотре из гибридного классического набора страниц ASP и .NET.

Цель - перейти на.NET 4.0, использующий EF 4.1 с Fluent API и продолжающий максимально использовать существующие базы данных.

Ключевые классы:

public class EntityBase
{
    public int Id { get; set; }
}

public class User : EntityBase
{
    public string UserName { get; set; }
...
}

Конфигурации:

internal class ConfigurationBase<T> : EntityTypeConfiguration<T> where T : EntityBase
{
    protected ConfigurationBase()
    {
        HasKey(t => t.Id);
    }
}

internal class UserConfiguration : ConfigurationBase<User>
{
    internal UserConfiguration()
    {
        Property(p => p.Id)
            .HasColumnName("Person_Id")
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
            .IsRequired();
        Property(p => p.UserName)
            .HasMaxLength(64);
        ToTable("Person");
    }
}

контекст все настроен в DbContext.OnModelCreating как:

    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new UserConfiguration());
    }

И все в порядке, когда я получаю доступ к данным напрямую через контекст, например:

    public override IQueryable<User> GetAll()
    {
        return UnitOfWork.Context.Users;
    }

Но когда я пытаюсь использоватьсуществующий sproc, который содержит следующее:

SELECT  p.Person_Id,
        p.IsUser,
        p.FirstName,
        p.LastName,
        p.UserName,
        p.Email,
        p.CreatedBy,
        p.CreatedDate,
        p.IsActive,
        p.ModifiedBy,
        p.ModifiedDate
FROM    Person p 
WHERE   p.UserName = @UserName
AND     p.IsActive = 1

Я выполняю следующее:

    public User AuthorizeUser(string userName)
    {
        SqlParameter p = new SqlParameter { 
            DbType = DbType.String,
            ParameterName = "UserName",
            Size = 64,
            Value = userName
        };
        object[] parameters = new object[] {p};

        return UnitOfWork.Context.Users.SqlQuery(CPODSStoredProcedures.User_AuthorizeUser, parameters).FirstOrDefault();
    }

И получаю: Считыватель данных несовместим с указанным пользователем.Элемент типа «Id» не имеет соответствующего столбца в считывателе данных с тем же именем.

Я проследил выполнение, и конфигурации читаются, поэтому я делаю что-то не так,или выполнение sproc SqlQuery не обращает внимания на то, как в этом случае переназначается базовый Id на Person_Id.

Заранее спасибо!G

Ответы [ 4 ]

3 голосов
/ 16 октября 2012

Отображение несовместимых sproc (или преобразование наборов результатов sproc в новые формы) в вашу объектную модель так же просто, как использование таблицы var и sp_executesql в качестве пакета, предоставленного в вашем вызове DbContext.SqlQuery (). Смотрите мой блог для рабочего примера этого в действии ->

http://blogs.msdn.com/b/schlepticons/archive/2012/10/15/yes-you-can-execute-parameterized-sprocs-with-ef-fluent-api-code-only-and-more.aspx

2 голосов
/ 13 июня 2011

EF 4.1 Code First (т.е. свободный API, который вы пытаетесь использовать) не поддерживает хранимые процедуры. Смотрите здесь .

Если вы хотите сделать это с EF, у вас нет выбора, кроме как создать модель (или, возможно, подождать до следующего выпуска). Лично я не думаю, что это проблема, потому что, поскольку база данных уже существует, создать модель с использованием DB First очень просто (наведите ее на эти таблицы и скажите «построить это»). Затем вы можете переключить EF на использование генератора DbContext и получить хорошие чистые классы POCO для работы с вашими данными. Вот простое объяснение, как это сделать.

Я знаю, что свободный API - это блестящая вещь, соответствующая модному слову, прямо сейчас, но она также нова в этом выпуске EF, и пока еще не все. Унаследованное приложение избавит вас от огромного количества головной боли, если вместо этого просто использовать модель DB First и генераторы классов POCO.

1 голос
/ 13 июня 2011

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

  1. Перейти к обновлению модели из базы данных.

  2. На экране «Добавить» найдите хранимую процедуру, которую вы хотите использовать, и установите флажок рядом с ней.

  3. Нажмите "Готово".

  4. Щелкните правой кнопкой мыши область конструктора EF и выберите «Добавить»> «Импорт функций».

  5. Выберите процесс, который вы хотите отобразить.

  6. Нажмите «Получить информацию о столбце».

  7. Нажмите создать новый "Сложный тип". (или если у вас есть сопоставленный объект, вы можете вернуть экземпляр объекта вместо сложного типа.)

  8. Нажмите ОК. Вы сделали.

После добавления функции импорта у вас будет метод для вашего объекта контекста EF, например ::

EntityContainter context = new EntityContainer();
User user = context.AuthorizeUser(username);

Я написал блог об этом процессе, здесь: http://www.codetunnel.com/blog/post/53/how-to-map-a-stored-procedure-to-an-entity-in-entity-framework-4

Надеюсь, это поможет!

0 голосов
/ 12 июня 2011

Я отказался от EntityFramework для nHibernate пару версий назад, но я почти уверен, что ваши свойства Id и UserName должны быть помечены как виртуальные, как в большинстве POCO, используемых в ORM, нет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...