簡體   English   中英

如何忽略實體框架中的非抽象基類?

[英]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.ObjectsList<MyDerivedClass>轉換的屬性,並使用此新派生的類代替MyClass

更新2:通過MyClass2.DerivedObjects屬性訪問時,將MyClass.ObjectsMyBaseClass實例自動轉換為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM