Как динамически сопоставить модель платформы Entity с именем таблицы - PullRequest
20 голосов
/ 07 августа 2010

Используя подход, основанный на коде, я хотел бы отобразить одну модель на несколько имен таблиц динамически .В настоящее время я могу сделать что-то вроде modelBuilder.Entity(Of Person)().MapSingleType().ToTable("Managers"), но поскольку метод OnModelCreating вызывается только один раз, я не могу сопоставить его с другими именами таблиц на лету.

В нашей текущей версии LinqToSql мы переопределяемMetaModel.GetTable () и возвращая новый TableAttribute с нашим динамическим именем.Я не нашел такого атрибута в EF (даже если бы он был, я бы не знал, как это переопределить).Итак, мой вопрос: возможно ли сделать это (пока)?

Обновление

Я обнаружил, что могу помешать методу OnModelCreating кэшировать сопоставления, вызвав

modelBuilder.CacheForContextType = false;

В результате я могу назначить определения таблиц при создании экземпляра объекта.Это не совсем то, как я хотел сделать, но это работает.

Обновление

О, мальчик, вышеописанное было большой ошибкой ... Кэширование существует по причине!:) Так что я вернулся к исходной точке с сопоставлением объектов POCO.Я опубликую обновление, если найду решение.

Финал

Если кому-то все равно, как я решил эту проблему, вот вам:

Сначала ясоздал отдельную библиотеку с таблицами POCO и интерфейсом

public interface IDataContext {
    System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }

    int SaveChanges();
}


public class TableGeneric {
    [Key]
    public int Column1 { get; set; }
    public string Column2 { get; set; }
    public DateTime Column3 { get; set; }
    public string Column4 { get; set; }
    public string Column5 { get; set; }
}

Затем, используя CSharpCodeProvider, я создал класс, который принимает следующий шаблон и превращает его в определение типа:

class DataContext : System.Data.Entity.DbContext, IDataContext {
    public System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder) {
        modelBuilder
            .Entity<ContextTesting.Interfaces.EF.TableGeneric()
                .MapSingleType()
                .ToTable("$TableName$");
    }
}

С помощью сгенерированного типа я могу создать экземпляр, поэтому здесь мы идем

Type typeAccountants = BuildContext.CreateGenericTable("Accountants");
IDataContext context = (IDataContext)Activator.CreateInstance(typeAccountants);

Тогда все остальное, как если бы у вас был обычный DataContext.Надеюсь, это поможет кому-то еще.

1 Ответ

13 голосов
/ 03 ноября 2010

Если кому-то все равно, как я в настоящее время решил эту проблему, вот вам:

Сначала я создал отдельную библиотеку с таблицами POCO и интерфейсом

public interface IDataContext {
    System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }

    int SaveChanges();
}


public class TableGeneric {
    [Key]
    public int Column1 { get; set; }
    public string Column2 { get; set; }
    public DateTime Column3 { get; set; }
    public string Column4 { get; set; }
    public string Column5 { get; set; }
}

Затем, используяCSharpCodeProvider Я создал класс, который берет следующий шаблон и превращает его в определение типа:

class DataContext : System.Data.Entity.DbContext, IDataContext {
    public System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder) {
        modelBuilder
            .Entity<ContextTesting.Interfaces.EF.TableGeneric()
                .MapSingleType()
                .ToTable("$TableName$");
    }
}

С сгенерированным типом я могу создать экземпляр, поэтому мы идем

Type typeAccountants = BuildContext.CreateGenericTable("Accountants");
IDataContext context = (IDataContext)Activator.CreateInstance(typeAccountants);

Тогда все остальное, как если бы у вас был обычный DataContext.Надеюсь, это поможет кому-то еще.

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