繁体   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