如何快速切换Database-First模式下EF的实体映射目标表?
解决方案
方法一:实体部分类+条件编译数据注解(推荐)
由于EDMX自动生成的Foo实体是partial类,我们可以在单独的文件中创建同名的partial类,通过条件编译动态指定实体映射的表名,完全不会被EDMX重新生成的代码覆盖:
// 新建Foo.partial.cs文件,与自动生成的Foo.cs同命名空间 public partial class Foo { #if USETHEOTHERTABLE // 编译时定义USETHEOTHERTABLE宏时,映射到Foo2表 [System.ComponentModel.DataAnnotations.Schema.Table("Foo2")] #endif }
配置说明:
- 确保
Foo2表的字段结构、类型与原Foo表完全一致,否则EF会抛出映射验证错误。 - 在项目属性的「生成」选项卡中,添加
USETHEOTHERTABLE编译符号(或在代码开头添加#define USETHEOTHERTABLE),即可触发表映射切换。
方法二:DbContext部分类+动态修改映射(进阶)
如果不想使用数据注解,可以通过ObjectContext的元数据工作区动态修改映射关系,在MyDatabaseEntities的部分类构造函数中实现:
// 新建MyDatabaseEntities.partial.cs文件 public partial class MyDatabaseEntities { public MyDatabaseEntities() : base("name=MyDatabaseEntities") { #if USETHEOTHERTABLE var objectContext = ((IObjectContextAdapter)this).ObjectContext; var workspace = objectContext.MetadataWorkspace; // 查找Foo实体的映射项 var entitySet = workspace.GetItem<EntityContainer>("MyDatabaseEntitiesContainer", DataSpace.CSpace).EntitySets.First(s => s.Name == "Foo"); var mapping = workspace.GetItems<EntityContainerMapping>(DataSpace.CSSpace).First().EntitySetMappings.First(em => em.EntitySet == entitySet); // 修改映射到Foo2表 var storeEntitySet = workspace.GetItem<EntityContainer>("MyDatabaseEntitiesStoreContainer", DataSpace.SSpace).EntitySets.First(s => s.Name == "Foo2"); mapping.SetTargetEntitySet(storeEntitySet); #endif } }
注意事项:
- 需要替换代码中的
MyDatabaseEntitiesContainer和MyDatabaseEntitiesStoreContainer为你EDMX中实际的容器名称(可在EDMX的XML视图中查看)。 - 此方法更灵活,但实现复杂度较高,适合需要动态切换多表的场景。
关于你顾虑的说明
- 自动生成的
OnModelCreating抛出异常:这是EF针对Database/Model First模式的设计,该方法在EDMX模式下根本不会被调用,因为EF直接使用EDMX文件中的模型定义,而非Code First的Fluent API配置,所以无法通过重写该方法实现表映射切换。 - 避免代码被覆盖:上述两种方法都使用了独立的partial类文件,与EDMX自动生成的
*.Designer.cs文件完全分离,重新生成EDMX时只会覆盖自动生成的代码,不会影响我们自定义的配置。
内容的提问来源于stack exchange,提问作者Matt Burland
相关产品推荐
相关产品推荐

