Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF4 CTP5:通过MEF模块-TPH-OnModelCreating扩展模型_C#_.net_Entity Framework 4_Mef_Entity Framework Ctp5 - Fatal编程技术网

C# EF4 CTP5:通过MEF模块-TPH-OnModelCreating扩展模型

C# EF4 CTP5:通过MEF模块-TPH-OnModelCreating扩展模型,c#,.net,entity-framework-4,mef,entity-framework-ctp5,C#,.net,Entity Framework 4,Mef,Entity Framework Ctp5,很抱歉没有找到更好的标题。我试图通过MEF模块扩展EF4 CTP5模型:其思想是指定一些基本实体。这些基本实体位于解决方案模型程序集中上下文类的旁边 例如,将有一个名为Variable的实体。变量是一个非常通用的实体,我希望应用程序的一些模块指定提供更详细属性的特殊变量实体,但它们应该存储在同一个表中(TPH-每个层次的表) 为此,我指定了一个接口IModelContextension public interface IModelContextExtension { void OnMo

很抱歉没有找到更好的标题。我试图通过MEF模块扩展EF4 CTP5模型:其思想是指定一些基本实体。这些基本实体位于解决方案模型程序集中上下文类的旁边

例如,将有一个名为Variable的实体。变量是一个非常通用的实体,我希望应用程序的一些模块指定提供更详细属性的特殊变量实体,但它们应该存储在同一个表中(TPH-每个层次的表)

为此,我指定了一个接口IModelContextension

public interface IModelContextExtension
{
    void OnModelCreating(IModelBuilderFacade modelBuilder);
}
要使用自定义变量的每个模块都必须导出一个实现此接口的类。在模型的OnModelCreating方法中,我循环每个注册的模块,并调用该模块的OnModelCreating方法。然后,它可以在提供的IModelBuilderFacade上调用例如“RegisterVariableType”,以宣布变量派生类型(例如MySpecialVariable2)

**有趣的是:** RegisterVariableType方法似乎工作得很好,除非变量派生类型位于另一个(MEF加载的)程序集中。如果我从另一个模块注册一个变量,那么完整的映射似乎会被破坏。因为,当我现在尝试向其存储库添加变量时,它在添加过程中崩溃,并说:“序列不包含任何元素”。如果我从加载的模块中删除该类型,它将按预期工作

如果有人感兴趣,我会发布我的推荐资料,但我相信这不是问题所在

这里是my context(派生自DbContext)类的OnModelCreating方法:

以下是地图功能:

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);
}
私有静态无效映射(ModelBuilder ModelBuilder、IEnumerable类型、字符串表),其中T:class
{
var entityTypeConfigurarion=modelBuilder.Entity();
foreach(类型中的变量variableType)
{
如果(!typeof(T).IsAssignableFrom(variableType))
{
抛出新的InvalidOperationException(string.Format(“无法将类型{0}映射到类型{1}”)、variableType、typeof(T));
}
//#1:获取EntityTypeConfiguration的通用映射方法
MethodInfo genericMapMethod=GetGenericeEntityTypeConfigurationMapMethod(variableType);
//#2:获取RequiredMappingActionFactory的通用类型
var requiredMappingFactoryType=typeof(RequiredMappingActionFactory)。MakeGenericType(variableType);
//#3从通用映射工厂获取操作
var action=requiredMappingFactoryType.GetProperty(“RequiredMappingAction”).GetValue(null,null);
实体类型配置=
genericMapMethod.Invoke(
entityTypeConfigurarion,
BindingFlags.Public | BindingFlags.Instance,
无效的
新的[]{/*和*/action/*放在这里*/},
null)作为EntityTypeConfiguration;
}
if(entityTypeConfigurarion==null)
{
抛出新的CompositionException(“出现了严重错误!”);
}
entityTypeConfigurarion.ToTable(表格);
}
私有静态方法信息GetGenericeEntityTypeConfigurationMapMethod(类型variableType),其中T:class
{
var映射法=
typeof(EntityTypeConfiguration).GetMethods()。其中(
mi=>mi.Name==“Map”&&mi.IsGenericMethodDefinition).FirstOrDefault();
返回mapMethod.MakeGenericMethod(variableType);
}
这里是所需的MappingActionFactory

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);
    }
}
内部静态类RequiredMappingActionFactory其中T:class
{
公共静态字符串鉴别器column=“鉴别器”;
公共静态操作RequiredMappingAction{get{return RequiredAction;}}
公共静态void RequiredAction(EntityMappingConfiguration配置)
{
configuration.Requires(DiscriminatorColumn).HasValue(typeof(T).Name);
}
}
希望有人能帮我, 致以最良好的祝愿

切里奥,
克里斯

实体框架4.1 RC发布! 我试过了,我成功了:-)

请参见此处的自定义映射函数,该函数允许动态添加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);
}
受保护的void映射实体(
DbModelBuilder modelBuilder,类型entityType,字符串toTable,字符串鉴别器Column=“鉴别器”)
{
var方法=
GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)。其中(
mi=>mi.Name.StartsWith(“MapEntity”)&&mi.IsGenericMethodDefinition.FirstOrDefault();
var genericMethod=method.MakeGenericMethod(entityType);
Invoke(这个,新对象[]{modelBuilder,toTable,discriminatorColumn});
}
受保护的空映射实体(
DbModelBuilder modelBuilder,字符串toTable,字符串鉴别器column=“鉴别器”)
式中T:类,属性
{
var config=modelBuilder.Entity().Map(
实体=>
{
entity.MapInheritedProperties();
entity.Requires(discriminatorColumn).HasValue(typeof(T).FullName).iso可选();
});
配置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");
    }
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
MapEntity(modelBuilder,toTable:“变量”);
MapEntity(modelBuilder,toTable:“变量”);
foreach(ModelExtensions.SelectMany中的var entityType(modelExtension=>modelExtension.IntroducteModelentities())
{
MapEntity(modelBuilder、entityType、toTable:“变量”);
}
}
干杯,
Chris

如果有人感兴趣,我将通过电子邮件发送解决方案(是一个测试项目)。我对上述代码进行了更多测试,发现它确实是实体类的位置(程序集)。创建SimpleEntity后,我将其2个派生项放入模型程序集中(MySimpleEntity和MySimpleEntity2),它们被正确映射和加载,但位于另一个程序集中的第3个类(MySimpleEntity3)将使
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");
    }
}