![](/img/trans.png)
[英]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.