XAF之数据库数据的预填充

来源:互联网 发布:mac win8开始菜单不见 编辑:程序博客网 时间:2024/06/02 23:07

         在设计XAF程序时有一个优点,可以脱离底层数据库的细节,不必了解到底是用的MSSQL或ORACL,只需要了解设计的Business Object,或者称之为XPObject,这些XPObject的类定义就对应了数据库的表定义,XPObject的每个持久化属性(字段)相应地对应了数据表的字段,一个XPObject对象也就对应了数据库表的一条记录,所有同类型XPObject的集合构成了一张数据表。另外,XPObject使用了AssociationAttribute特性标记来表示数据表的外键关系。而这就为我们预填充数据库带来了小小的麻烦:数据库中的外键字段可能是一个int类型,而在XPObject中该外键被表示为所引用表对应的XPObject类型,并以AssociationAttribute特性修饰,而当我们有大量预填充的数据时,我们通常是将这些数据放在独立的文件中(比如XML)而不是硬编码进程序,然后读取这些文件再填充数据库,现在问题来了,你的XML文档保存的引用外键若为5,那么怎样另XPObject保存该外键为一个对象呢?使用底层SQL语句显示不是理想的解决办法。这里,我写了一个专门的填充类DatabaseDump解决这个问题。

1.DatabaseDump使用方法

IList<Dictionary<string, string>> Records = new List<Dictionary<string, string>>();//......将数据放入Records集合中......DatabaseDump<MyPerson> dump = new DatabaseDump<MyPerson>(ObjectSpace);dump.DumpTable(Records);ObjectSpace.CommitChanges();
    这样,在软件/数据库设计时,需要做的仅仅是修改数据文件和XPObject的定义,另外可能要修改数据文件的读取程序。

    下面给出我的源码,功能很简单:

//类型T为所要填充的XPObject,完成填充后,需要手动ObjectSpace.CommitChanges()    class DatabaseDump<T>    {        IObjectSpace ObjectSpace;        public DatabaseDump(IObjectSpace ObjectSpace)        {            this.ObjectSpace = ObjectSpace;        }        //判断MyType类型中的PropertyName属性是否是一个外键        private bool IsForeignKey(Type MyType, string ProperyName)        {            System.Reflection.PropertyInfo pi = MyType.GetProperty(ProperyName);            bool IsAssociation = Attribute.GetCustomAttribute(pi, typeof(DevExpress.Xpo.AssociationAttribute)) is DevExpress.Xpo.AssociationAttribute;            return IsAssociation && pi.PropertyType.IsSubclassOf(typeof(DevExpress.Xpo.XPBaseObject));        }        //填充表的记录,一条记录为一个Dictionary        public void DumpTable(IList<Dictionary<string, string>> Records)        {            T obj=default(T);            foreach (Dictionary<string, string> record in Records)            {                obj = ObjectSpace.CreateObject<T>();                foreach (KeyValuePair<string, string> cell in record)                {                    if (IsForeignKey(typeof(T), cell.Key))                    {                        Type foreignType = typeof(T).GetProperty(cell.Key).PropertyType;                        string foreignKeyName = ObjectSpace.GetKeyPropertyName(foreignType);                        CriteriaOperator filter = new BinaryOperator(foreignKeyName, cell.Value, BinaryOperatorType.Equal);                        object foreign = ObjectSpace.FindObject(foreignType, filter,true);                        if(foreign!=null)                            typeof(T).GetProperty(cell.Key).SetValue(obj, cell.Value, null);                    }                    else                    {                        typeof(T).GetProperty(cell.Key).SetValue(obj, cell.Value, null);                    }                }            }        }    }

        需要说明一点的是,如果需要填充很多张表,而你的XPObject中主键标识为自增id([Key[true])或数据库端设置为自增,那么创建对象时赋值的ID可能和最终存储的ID是不一致的,所以最好是在所有数据填充完毕(都保存在ObjectSpace中)后,一起提交更改,避免错误。所以,我在类中使用了带bool参数的ObjectSpace.FindObject方法,否则是找不到未提交的记录的。

2.数据文件

         选择合适的格式保存数据文件,并编写对应的读取程序。我使用了简单的XML文件,并就近使用了C#的XmlTextReader解析文件,由于没有什么多余的信息,故这种无后退的读取方式也是无伤大雅的。