English 中文(简体)
EF4 CTP5:通过微型信贷协议扩展模型 模块 - TPH - OnModelCreating
原标题:EF4 CTP5: Extend Model via MEF Module - TPH - OnModelCreating

i 担心找不到更好的标题。 我正试图通过MEF扩大EF4CTP5模式。 模块: 理想是调和一些基本实体。 这些基本实体位于我的背景类别旁,位于我的解决方案模拟大会。

例如,将有一个称为可变的实体。 可变性是一个非常一般的实体,需要一些应用模块来说明特别可变实体的巫术提供更为详细的特性,但应将其储存在同一表格中(TPH——每座等级表)。

To do so, i specified an interface IModelContextExtension

public interface IModelContextExtension
{
    void OnModelCreating(IModelBuilderFacade modelBuilder);
}

想要使用习俗变量的每个模块都必须出口一个能够实施这一接口的类别。 在模型的“模拟”方法中,即每个已登记的模块,并使用该模块的“模拟方法”。 然后,它可以在IModelBuilderFacade提供的“RegisterVariableType”上宣布一个Variable-Derived-Type(例如MySpecialVariable2)。

** The interesting part: ** The RegisterVariableType method seems to work very good, except if the Variable-Derived-Type is located in another (MEF-Loaded) assembly. If i register a Variable from another module, than the complete mapping seems to be damaged. Because, when i now try to add a Variable to its Repository, it crashs during the add saying: "Sequence contains no elements". If i remove the type from the loaded module, it works like expected.

如果有人感兴趣,但我肯定会说,这不是问题,那么我就会把保存人放在一边。

这里,从我的背景(从DbContext)类中得出ModelCreating方法:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    var modelBuilderFacade = new ModelBuilderFacade(modelBuilder);

    modelBuilder.Entity<Variable>().HasKey(x => new { x.Id });

    ////////////////////////////////////
    // register derived VariableTypes

    modelBuilderFacade.RegisterVariableType(typeof(MySpecialCyclicVariable));
    modelBuilderFacade.RegisterVariableType(typeof(MyVerySpecialVariable));

    //modelBuilder.Entity<Variable>().HasKey(x => new { x.Id }); modelBuilder.Entity<Variable>()
    //    .Map<MySpecialVariabe>(m => m.Requires(DiscriminatorColumn).HasValue(typeof(MySpecialVariabe).Name))
    //    .Map<MyVerySpecialVariable>(m => m.Requires(DiscriminatorColumn).HasValue(typeof(MyVerySpecialVariable).Name))
    //    .ToTable(VariableTable);

    if (ModelExtensions != null)
    {
        foreach (var modelContextExtension in ModelExtensions)
        {
            modelContextExtension.OnModelCreating(modelBuilderFacade);
        }
    }

    Map<Variable>(modelBuilder, modelBuilderFacade.VariableTypes, VariableTable);

    ////////////////////////////////////
}

The RegisterVariableType function adds the (Variable derived) types to an IEnumerable stored in the modelBuilderFacade.

在添加了这些类型之后,即我自己的地图功能,以图绘制地图。

[Export(typeof(IModelContextExtension))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class Context : IModelContextExtension
{
    public void OnModelCreating(IModelBuilderFacade modelBuilder)
    {
        modelBuilder.RegisterVariableType(typeof(MyVerySpecialVariable2));
    }
}

地图功能:

private static void Map<T>(ModelBuilder modelBuilder, IEnumerable<Type> types, string table) where T : class
{
    var entityTypeConfigurarion = modelBuilder.Entity<T>();

    foreach (var variableType in types)
    {
        if (!typeof(T).IsAssignableFrom(variableType))
        {
            throw new InvalidOperationException(string.Format("Cannot map type  {0}  to type {1}", variableType, typeof(T)));
        }

        // #1: Get the generic Map method of the EntityTypeConfiguration<T>
        MethodInfo genericMapMethod = GetGenericEntityTypeConfigurationMapMethod<T>(variableType);

        // #2: Get generic type of RequiredMappingActionFactory
        var requiredMappingFactoryType = typeof(RequiredMappingActionFactory<>).MakeGenericType(variableType);

        // #3 get the action from generic mapping factory
        var action = requiredMappingFactoryType.GetProperty("RequiredMappingAction").GetValue(null, null);

        entityTypeConfigurarion =
            genericMapMethod.Invoke(
                entityTypeConfigurarion,
                BindingFlags.Public | BindingFlags.Instance,
                null,
                new [] { /* and the */ action /* goes here */ },
                null) as EntityTypeConfiguration<T>;
    }

    if (entityTypeConfigurarion == null)
    {
        throw new CompositionException("Something went terrible wrong!");
    }

    entityTypeConfigurarion.ToTable(table);
}

private static MethodInfo GetGenericEntityTypeConfigurationMapMethod<T>(Type variableType) where T : class
{
    var mapMethod =
        typeof(EntityTypeConfiguration<T>).GetMethods().Where(
            mi => mi.Name == "Map" && mi.IsGenericMethodDefinition).FirstOrDefault();
    return mapMethod.MakeGenericMethod(variableType);
}

以及此处要求采取的行动

internal static class RequiredMappingActionFactory<T> where T : class
{
    public static string DiscriminatorColumn = "Discriminator";

    public static Action<EntityMappingConfiguration<T>> RequiredMappingAction { get { return RequiredAction; } }

    public static void RequiredAction(EntityMappingConfiguration<T> configuration) 
    {
        configuration.Requires(DiscriminatorColumn).HasValue(typeof(T).Name);
    }
}

hopefully someone can help me, best regards,

cherio, Chris

最佳回答

Entity Framework 4.1 RC is released! I tried it and i succeeded :-)

http://blogs.msdn.com/b/adonet/archive/201103/15/ef-4-1-release-candidate- available.aspx” rel=“nofollow”http://blogs.msdn.com/b/adonet/archive/03/15/ef-4-1-release-candidate- available.aspx

在这里,海关绘图功能使TPH绘图能够动态地补充。

protected void MapEntity(
    DbModelBuilder modelBuilder, Type entityType, string toTable, string discriminatorColumn = "Discriminator")
{
    var method =
        GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(
            mi => mi.Name.StartsWith("MapEntity") && mi.IsGenericMethodDefinition).FirstOrDefault();

    var genericMethod = method.MakeGenericMethod(entityType);

    genericMethod.Invoke(this, new object[] { modelBuilder, toTable, discriminatorColumn });
}

protected void MapEntity<T>(
    DbModelBuilder modelBuilder, string toTable, string discriminatorColumn = "Discriminator")
    where T : class, IEntity
{
    var config = modelBuilder.Entity<T>().Map(
        entity =>
            {
                entity.MapInheritedProperties();
                entity.Requires(discriminatorColumn).HasValue(typeof(T).FullName).IsOptional();
            });

    config.ToTable(toTable);
}

以及使用实例:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    MapEntity<Variable>(modelBuilder, toTable: "Variables");
    MapEntity<Variable2>(modelBuilder, toTable: "Variables");

    foreach (var entityType in ModelExtensions.SelectMany(modelExtension => modelExtension.IntroduceModelEntities()))
    {
        MapEntity(modelBuilder, entityType, toTable: "Variables");
    }
}

cheers, Chris

问题回答

暂无回答




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签