Entity Framework 4 Code First Inheritance Solution с помощью Reflection - PullRequest
0 голосов
/ 02 апреля 2011

Я нашел несколько решений этой проблемы, некоторые из которых не работают, а некоторые нарушают принцип СУХОГО.

Я хочу, чтобы все мои объекты наследовали от Audit (который предоставляет свойства / столбцы IsActive, CreateDate, UpdateDate, CreateUser, & UpdateUser). Я могу заставить это работать нормально, но это создает проблему с именами столбцов, которые генерируются с помощью отношений (CreateUser_UserId & UpdateUser_UserId). Я бы предпочел CreateUserId и UpdateUserId. К сожалению, ColumnAttribute не работает так, как предлагали статьи / SO ответы. Тем не менее, Fluent API работает. Это просто нарушает СУХОЕ в том смысле, что каждая создаваемая мной сущность в конечном итоге делает что-то вроде этого:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
    // have to write these two lines for each new entity I create
    modelBuilder.Entity<User>().HasOptional(u => u.CreateUser).WithMany().HasForeignKey(u => u.CreateUserId).WillCascadeOnDelete(false);
    modelBuilder.Entity<User>().HasOptional(u => u.UpdateUser).WithMany().HasForeignKey(u => u.UpdateUserId).WillCascadeOnDelete(false);
}

Итак, я хочу использовать отражение, чтобы просто перебрать каждый отдельный тип, который расширяет Audit, и эффективно вызывать эти цепочки методов в моем modelBuilder. Вот как далеко я продвинулся в поисках, прежде чем полностью потерял сознание:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
    var types = GetTypesInheritingFrom(typeof (Audit)); // implementation unimportant
    foreach (var t in types) {
        var method = modelBuilder.GetType().GetMethod("Entity");
        var generic = method.MakeGenericMethod(t);
        var o = generic.Invoke(modelBuilder, null);
        // not sure how to proceed from here, HasOptional() requires an Expression<Func<t, TTargetEntity>>
        // not sure if WithMany() is actually required??
        // not sure what to do with HasForeignKey() either, it requires an Expression<Func<User, Guid>>
    }
}

Это в основном первая реальная вещь, которую я сделал в C # /. Net, и мне она кажется очень сложной. Если я пойду по этому пути совершенно неправильно, пожалуйста, дайте мне альтернативу, которая не работает для меня. Мне не очень нравится идея шаблона T4 или интерфейса - это повторяющийся код, который я бы предпочел не поддерживать.

Ответы [ 2 ]

3 голосов
/ 02 апреля 2011

Создайте вспомогательный метод:

private void MapUserRelations<TEntity>(DbModelBuilder modelBuilder) 
    where TEntity : Audit
{
    modelBuilder.Entity<TEntity>().HasOptional(u => u.CreateUser).WithMany().HasForeignKey(u => u.CreateUserId).WillCascadeOnDelete(false);
    modelBuilder.Entity<TEntity>().HasOptional(u => u.UpdateUser).WithMany().HasForeignKey(u => u.UpdateUserId).WillCascadeOnDelete(false); 
}

и используйте свое отражение:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{
    var types = GetTypesInheritingFrom(typeof (Audit)); 
    foreach (var t in types) 
    {
        var method = this.GetType().GetMethod("MapUserRelations");
        var generic = method.MakeGenericMethod(t, BindingFlags.NonPublic | BindingFlags.Instance);
        generic.Invoke(this, new Object[] { modelBuilder });
    }
}
2 голосов
/ 02 апреля 2011

Является ли сам объект аудита? Если да, вы можете применить эти правила непосредственно к Аудиту.

Я также считаю, что наследование - это плохо. Я бы использовал свойство сложного типа вместо этого. Увидеть: http://weblogs.asp.net/manavi/archive/2011/03/28/associations-in-ef-4-1-code-first-part-2-complex-types.aspx

И почему вы хотите изменить способ генерации схемы БД. Прежде всего, используя код, это должно быть скрыто. Единственная причина, по которой я вижу это, - это когда у вас уже есть схема БД, и вы хотите создать для нее свое отображение.

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