[英]How to to handle abstract base class in entity framework(code first)?
[英]How to ignore a not abstract base class in Entity Framework?
我的模型的基类不是抽象的,并且没有定义任何键(这是我无法修改的外部定义的类)。 相反,我定义了一个具有MyID
属性的派生类作为键。 像这样:
public class MyBaseClass // From external assembly
{
//public int ID { get; set; }
public string Name { get; set; }
}
public class MyClass // From external assembly
{
public int ID { get; set; }
public List<MyBaseClass> Objects { get; set; }
}
public class MyDerivedClass : MyBaseClass
{
public Guid MyID { get; set; }
public MyDerivedClass()
{
MyID = Guid.NewGuid();
}
}
public class MyClasses : DbContext
{
public DbSet<MyClass> Classes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyDerivedClass>().HasKey(entity => entity.MyID);
modelBuilder.Entity<MyDerivedClass>().Map(entity =>
{
entity.MapInheritedProperties();
entity.ToTable("MyBaseClass");
});
modelBuilder.Ignore<MyBaseClass>();
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer<MyClasses>(new DropCreateDatabaseIfModelChanges<MyClasses>());
var myClass = new MyClass() // Just as example, in real code is somethog like: MyClass myClass = ExtenalAssembly.getMyClass()
{
ID = 0,
Objects = new List<MyBaseClass>()
{
new MyBaseClass()
{
//ID = 0,
Name = "My Test Object 1"
},
new MyBaseClass()
{
//ID = 1,
Name = "My Test Object 2"
}
}
};
Mapper.CreateMap<MyBaseClass, MyDerivedClass>();
for (var index = 0; index < myClass.Objects.Count; index++)
{
myClass.Objects[index] = Mapper.Map<MyDerivedClass>(myClass.Objects[index]);
}
var myObjects = new MyClasses();
myObjects.Classes.Add(myClass);
myObjects.SaveChanges();
}
}
如果我注释掉modelBuilder.Ignore<MyBaseClass>();
运行时引发异常,因为MyBaseClass
没有定义键; 另一方面,当我包括该行以不保存基类实例的状态,而仅保存派生类实例的状态时,系统不会在生成的表中保留任何数据。
为了只保留派生实例的状态该怎么办?
我使用NuGet的EF6.0.1运行您的解决方案,并且全部签出(没有错误)。 我正确地保留了数据,并且两个字段都按预期保留了。
如果我正确地阅读了您的声音,听起来您不希望基类的Name
属性映射到EF。 如果是这种情况,可以将此行添加到modelBuilder中并重新生成迁移文件。
modelBuilder.Entity<MyDerivedClass>().Ignore(d => d.Name);
这给了我下面的“向上”脚本
CreateTable(
"dbo.MyBaseClass",
c => new
{
MyID = c.Guid(nullable: false),
})
.PrimaryKey(t => t.MyID);
运行main之后,只有ID会保留。
更改导航集合属性,以将派生类型用作通用类型参数(毕竟,您要让EF忽略MyDerivedType
)。 这将使事情起作用。
更新:如果您不能更改MyClass
类,则从MyClass
派生一个新类,该类具有将MyClass.Objects
与List<MyDerivedClass>
转换的属性,并使用此新派生的类代替MyClass
。
更新2:通过MyClass2.DerivedObjects
属性访问时,将MyClass.Objects
的MyBaseClass
实例自动转换为MyDerivedClass
实例, MyBaseClass
使代码更安全。 这允许将MyBaseClass
实例添加到MyClass.Objects
列表(如问题中所示),而不必担心在使用MyClass2.DerivedObjects
访问时MyClass2.DerivedObjects
无效的MyClass2.DerivedObjects
异常。
更新3:再次更新,使MyClass2
包装MyClass
而不是从中派生
// DbSet property in your DbContext
public DbSet<MyClass2> Classes { get; set; }
// continue to ignore MyBaseClass
...
modelBuilder.Ignore<MyBaseClass>();
...
public class MyBaseClass // From external assembly
{
//public int ID { get; set; }
public string Name { get; set; }
}
public class MyDerivedClass : MyBaseClass
{
public Guid MyID { get; set; }
public MyDerivedClass()
{
MyID = Guid.NewGuid();
}
public MyDerivedClass( MyBaseClass myBaseClass ) : this()
{
// map myBaseClass to `this` here:
this.Name = myBaseClass.Name;
}
}
public class MyClass
{
public int ID { get; set; }
public List<MyBaseClass> Objects { get; set; }
}
public class MyClass2
{
public static implicit operator MyClass( MyClass2 mc2 )
{
return mc2._myClass;
}
public virtual List<MyDerivedClass> Objects
{
get
{
for( int i = 0; i < _myClass.Objects.Count; ++i )
{
var o = _myClass.Objects[ i ];
if( null == ( o as MyDerivedClass ) )
{
_myClass.Objects[ i ] = new MyDerivedClass( o );
}
}
return _myClass.Objects.Cast<MyDerivedClass>().ToList();
}
set
{
_myClass.Objects = value.Cast<MyBaseClass>().ToList();
}
}
public int ID
{
get { return _myClass.ID; }
set { _myClass.ID = value; }
}
private MyClass _myClass;
public MyClass2()
{
_myClass = new MyClass();
}
public MyClass2( MyClass myClass )
{
if( null == myClass )
throw new ArgumentNullException( "myClass" );
_myClass = myClass;
}
}
应用代码:
using( var db = new TestContext() )
{
var myClass = new MyClass()
{
ID = 0,
Objects = new List<MyBaseClass>()
{
new MyBaseClass()
{
Name = "Object 1"
},
new MyBaseClass()
{
Name = "Object 2"
}
}
};
var myClass2 = new MyClass2( myClass );
db.Classes.Add( myClass2 );
db.SaveChanges();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.