如何动态地将继承属性添加到EF数据存储

本文关键字:添加 属性 EF 存储 数据 继承 何动态 动态 | 更新日期: 2023-09-27 18:17:05

在这篇文章中,我询问并回答了如何为类动态导入值&属性在EF/DbSet模型中没有硬编码。我简直不敢相信我跌跌撞撞了这么久才找到了一种方法。但是…

它揭示了一个问题,在Locals窗口中查找实例层次结构数小时无法解决:

虽然我可以在目标类上动态导入数据,但它从基类扩展的任何属性都会失败。上面最初的帖子在最后说明了这一点。在我们将数据导入到DataTable之后,问题就显现出来了。我们将遍历DataTable的列,使用数据库中匹配的Types来确定它们的类型(int、double等)。

要做到这一点,一行创建了我们查询信息的对象,虽然Child()属性一切正常,但一旦我们从Person()(基类)中命中一个,它就会失败,并产生一个空引用。

不重新发布整篇文章,我只粘贴相关的部分:

foreach (DataRow dr in dt.Rows) 
{
    i = 0; // I don't like to put var instantiation in a loop...
    // each drItem is the content for the row (theObj)
    foreach (string drItem in dr.ItemArray)
    {
        string entAttrName = dt.Columns[i].ToString();
        string entAttrValue = dr[i].ToString();
        // column (property) name:
        // the value of that property to load into this class' property
        // which type of data is this property? (string, int32, double...)
        // -also has data like if nullable, etc. of use in later refinements...
        TypeInfo thisTypeInfo = theObj.GetType().GetTypeInfo();
        // All details from the property to update/set:
 >>---> PropertyInfo theProp = thisTypeInfo.GetDeclaredProperty(entAttrName);

上面,最后一行没有给theProp分配一个有效的对象,而是给它一个null,这使得我们的程序在查询它的时候就停止了。

只要只从Child()类中导入值,上面链接中的例子(这段代码来自哪里)就可以正常工作。继承的属性导致它停在上面一行。

entAttrName只是属性名称的字符串,取自前面DataTable的标题行,并且(虽然忽略了上面的一些代码行)基本上做的事情类似:

var aClass = u.CreateInstanceOf(dt.TableName, pathToAssembly);
DbSet dbs = ctx.Set(aClass.GetType());
var theObj = dbs.Create(aClass.GetType());
foreach (DataRow dr in dt.Rows)...
foreach (string drItem in dr.ItemArray)...
string entAttrName = dt.Columns[i].ToString();
string entAttrValue = dr[i].ToString();
TypeInfo thisTypeInfo = theObj.GetType().GetTypeInfo();
PropertyInfo theProp = thisTypeInfo.GetDeclaredProperty(entAttrName); ******
if (theProp.PropertyType.ToString() == "System.String")
{
    theProp.SetValue(theObj, (String)entAttrValue);
}
else if (theProp.PropertyType.ToString().Contains("System.Int32"))
{
    theProp.SetValue(theObj, int.Parse(entAttrValue));
} else if...

我不能弄清楚为什么我的生活孩子()…

class Child : Person
{
    [Key]
    [Column(Order = 0)]
    public int Id { get; set; }
    public string sChildFoo { get; set; }
    public int iChildBar { get; set; }
    public double dChildBaz { get; set; }
}

…属性可以通过这行,但是Person()…

中的任何属性
public abstract class Person
{
    [Key]
    public int PersonId { get; set; }
    public int PersonAge { get; set; }
    public int PersonWeight { get; set; }
    public string PersonName { get; set; }
}

…失败。下面是程序的完整日志,显示了它停止的位置。在原始帖子处快照异常:

2016-11-08 15:03:12.9049 INFO Starting at 3:03:12 PM
2016-11-08 15:03:12.9801 INFO Created .Name: Qeququ Qequququ
2016-11-08 15:03:12.9838 INFO Created .sParentFoo: Kakikikiki
2016-11-08 15:03:13.9918 INFO wb.WorkSheets count: 2
2016-11-08 15:03:14.0007 INFO ws.Rows count: 3
2016-11-08 15:03:14.0007 INFO dt.Rows.Count: 2
2016-11-08 15:03:14.0007 INFO dt.Name: Child
2016-11-08 15:03:14.0666 INFO aClass.FullName: DynamicEFLoading.Child
2016-11-08 15:03:14.0666 INFO Creating 'dbs' object...
2016-11-08 15:03:14.0891 INFO GetType: DynamicEFLoading.Child
2016-11-08 15:03:14.0963 INFO ================= row ==================================
2016-11-08 15:03:14.0963 INFO ================= col 0 
2016-11-08 15:03:14.1105 INFO [0] Item: sChildFoo
2016-11-08 15:03:14.1105 INFO [0] Value: Norwich
2016-11-08 15:03:14.1105 INFO theProp.DeclaringType.FullName of attr: DynamicEFLoading.Child
2016-11-08 15:03:14.1265 INFO theProp.GetSetMethod(true).ToString() of attr: Void set_sChildFoo(System.String)
2016-11-08 15:03:14.1265 INFO theProp.GetType().ToString() of attr: System.Reflection.RuntimePropertyInfo
2016-11-08 15:03:14.1265 INFO theProp.Name of attr: sChildFoo
2016-11-08 15:03:14.1424 INFO theProp.PropertyType.ToString() of attr: System.String
2016-11-08 15:03:14.1424 INFO theProp.ReflectedType.ToString() of attr: DynamicEFLoading.Child
2016-11-08 15:03:14.1424 INFO theProp.ReflectedType.ToString() of attr: System.Void
2016-11-08 15:03:14.1557 DEBUG Set System.String value: Norwich
2016-11-08 15:03:14.1557 INFO ================= col 1 
2016-11-08 15:03:14.1557 INFO [1] Item: iChildBar
2016-11-08 15:03:14.1780 INFO [1] Value: 29884
2016-11-08 15:03:14.1780 INFO theProp.DeclaringType.FullName of attr: DynamicEFLoading.Child
2016-11-08 15:03:14.1919 INFO theProp.GetSetMethod(true).ToString() of attr: Void set_iChildBar(Int32)
2016-11-08 15:03:14.2113 INFO theProp.GetType().ToString() of attr: System.Reflection.RuntimePropertyInfo
2016-11-08 15:03:14.2113 INFO theProp.Name of attr: iChildBar
2016-11-08 15:03:14.2233 INFO theProp.PropertyType.ToString() of attr: System.Int32
2016-11-08 15:03:14.2368 INFO theProp.ReflectedType.ToString() of attr: DynamicEFLoading.Child
2016-11-08 15:03:14.2368 INFO theProp.ReflectedType.ToString() of attr: System.Void
2016-11-08 15:03:14.2607 DEBUG Set System.Int32 value: 29884
2016-11-08 15:03:14.2657 INFO ================= col 2 
2016-11-08 15:03:14.2851 INFO [2] Item: dChildBaz
2016-11-08 15:03:14.2978 INFO [2] Value: 1.2
2016-11-08 15:03:14.3184 INFO theProp.DeclaringType.FullName of attr: DynamicEFLoading.Child
2016-11-08 15:03:14.3305 INFO theProp.GetSetMethod(true).ToString() of attr: Void set_dChildBaz(Double)
2016-11-08 15:03:14.3305 INFO theProp.GetType().ToString() of attr: System.Reflection.RuntimePropertyInfo
2016-11-08 15:03:14.3457 INFO theProp.Name of attr: dChildBaz
2016-11-08 15:03:14.3682 INFO theProp.PropertyType.ToString() of attr: System.Double
2016-11-08 15:03:14.3910 INFO theProp.ReflectedType.ToString() of attr: DynamicEFLoading.Child
2016-11-08 15:03:14.4098 INFO theProp.ReflectedType.ToString() of attr: System.Void
2016-11-08 15:03:14.4098 DEBUG Set System.Double value: 1.2
2016-11-08 15:03:14.4098 INFO ================= col 3 
2016-11-08 15:03:14.4382 INFO [3] Item: PersonAge
2016-11-08 15:03:14.4609 INFO [3] Value: 34

有关完整的工作示例(包含此失败),请参阅此处的原始帖子。

===========================================================================

如何动态地将继承属性添加到EF数据存储

thisTypeInfo.GetDeclaredProperty获取由类型本身声明的属性,而不是它的超类型。使用thisTypeInfo.GetProperty。或者只是

theObj.GetType().GetProperty(entAttrName);