我使用实体框架6.2代码优先(.net框架4.6.1),并且我映射了几个实体以通过表属性进行查看。它适用于选择操作,我通过编写触发器来处理插入/更新/删除操作,以在sql服务器端进行查看。它可以按预期工作,但是当我添加新迁移时,实体框架会为使用的表属性生成RenameTable脚本(实际上是EF的预期行为)。但是我想拦截迁移生成,并将这些实体tableName更改为原始名称。
我的代码如下;
[MapToView("Users","UsersView")]
public class User
{
...
}
我写了MapToView Attribute,此属性由TableAttribute继承,并传递给TableAttribute的第二个参数。之所以创建此属性,是因为如果我拦截了迁移的生成,请使用此属性参数返回原始表名。
在这种情况下,当我运行“ add-migration migrationName”时,它将创建这样的迁移脚本;
RenameTable(name: "dbo.Users", newName: "UsersView");
但是我想在运行“ add-migration migrationName”脚本时创建空迁移。
有人可以帮助我吗?
答案 0 :(得分:2)
我解决了这个问题。 第一:问题在于;当我将实体映射到View EF Code-first时,会使用ViewName生成迁移。这是问题,因为我想使用“视图”而不是“表”。因此,我使用此说明解决了问题;
1-我创建了从EntityTypeConfiguration继承的BaseEntityConfiguration和所有实体配置类。 例如:
public class UserConfig: BaseEntityConfiguration<User> //Generic Type is Entity
{
public UserConfig()
{
}
}
2-我创建了TableAttribute继承的MapToViewAttribute
public class MapToViewAttribute : TableAttribute
{
public string TableName { get; }
public string ViewName { get; }
public MapToViewAttribute(string tableName, string viewName) : base(viewName)
{
TableName = tableName;
ViewName = viewName;
}
}
3-我使用MapToViewAttribute例如用户实体来使用View。
[MapToView("User","UserView")]
public class User
{
...
}
然后在BaseEntityConfiguration的构造函数中,我获得了通用类型和自定义属性。如果有任何实体具有MapToView属性,则将TableName参数传递给ToTable方法。因此,EF在运行时将View用于这些实体,但不会使用RenameTable创建迁移。
protected BaseEntityConfiguration()
{
var baseType = typeof(TEntityType);
var attributes = baseType.GetCustomAttributes(true);
foreach (var attr in attributes)
{
if (attr.GetType() == typeof(MapToViewAttribute))
{
var tableName = ((MapToViewAttribute)attr).TableName;
ToTable(tableName);
}
}
}
最后一个EF不使用您的配置文件,因此您必须告诉EF在DbContext类的InternalModelCreate方法中使用它。 我的实现是这样的
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var typesToRegister = Assembly.GetExecutingAssembly()
.GetTypes().Where(IsConfigurationType);
foreach (var type in typesToRegister)
{
dynamic configurationInstance = type.BaseType != null
&& type.BaseType.IsGenericType
&& type.BaseType.GetGenericTypeDefinition() == typeof(BaseEntityConfiguration<>)
? Activator.CreateInstance(type, culture)
: Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
modelBuilder.Types().Configure(t => t.ToTable(t.ClrType.Name));
BaseDbContext.InternalModelCreate(modelBuilder);
}
但是,如果使用这种方法,则必须创建插入,更新和删除触发器/规则(如果使用SQLServer触发器是一个选项,但是如果使用postgresql规则则更好),因为EF使用此视图进行插入,更新和删除操作。