解决方案 »

  1.   

    你不敢在实体类里定义个save方法,然后调用
    ProductInfo.Save和OrderInfo.Save
    不就得了
    不同的实体类,里面属性数量,属性名称,属性类型,都不一样,你要做个通用的save,还要考虑之后可能会出现的,现在未定义的实体类,你觉得现实么?
      

  2.   

    关键一点,即使你做成了,save完了
    那load又该怎么办,load之前你不知道要load的是什么,能load出来?
      

  3.   

    你想如何保存?数据库?缓存服务器?序列化成json或者xml?
      

  4.   

    为了懒省事,直接序列化反序列化不就得了,自己封装save干啥
      

  5.   

         /// <summary>
         /// 数据辅助类
       /// </summary>
        [Serializable]
        public class MonitorParam
        {        public string processPath;        /// <summary>
            /// 监测类型
            ///
            /// </summary>
            public int monitorType;
             }      private readonly string fileName = "process.dat";        /// <summary>
            /// 保存当前进程列表到文件
            /// </summary>
            /// <param name="filename"></param>
             public bool SaveProcessToFile(Dictionary<string, MonitorParam> processlist)
            {
                bool flag = false;
                try
                {
                    if (File.Exists(fileName))
                    {
                        File.Delete(fileName);
                    }
                    string xmlpath = AppDomain.CurrentDomain.BaseDirectory;
                    using (FileStream writer = new FileStream(xmlpath + @"\" + fileName, FileMode.OpenOrCreate))
                    {
                        BinaryFormatter formatter = new BinaryFormatter();                    formatter.Serialize(writer, processlist);
                    }
                    flag = true;
                }
                catch (Exception ex)
                {
                             }
                return flag;
            }
            /// <summary>
            /// 读取本地文件中的进程队列
            /// </summary>
            /// <param name="filename"></param>
            /// <returns></returns>
             public Dictionary<string, MonitorParam> GetProcessFromFile()
            {
                Dictionary<string, MonitorParam> result = new Dictionary<string, MonitorParam>();
                try
                {                string processPath = AppDomain.CurrentDomain.BaseDirectory;
                    string filePath = Path.Combine(processPath, fileName);
                    if (File.Exists(filePath))
                    {
                        using (FileStream reader = new FileStream(filePath, FileMode.Open))
                        {
                            BinaryFormatter formatter = new BinaryFormatter();
                            result = (Dictionary<string, MonitorParam>)formatter.Deserialize(reader);                    }
                    }
                }
                catch (Exception ex)
                {
                 
                }
                return result;        }
      

  6.   


    如何保存任意实体,就好像在问:如何打造一把万能锁钥1.如楼上所说的,每个实体类中,自定义save方法,通过实体.save()调用。
    2.还是要每个实体类中,自定义save方法。但是:使用简单工厂模式,在工厂中进行判断(用switch语句枚举判断。可以使用反射机制加速效率),并在工厂中实现实体.save()调用。客户端只需要
    Factory.Save(ProductInfo);
    Factory.Save(OrderInf9);

    就可以保存相应的实体。
    以此隐藏save方法的细节。
      

  7.   

    [Serializable]
            public class AnyClass
            {
                public object AnyData = null;
            }        /**/
            /// <summary>
            /// 将一个object对象序列化,返回一个byte[]
            /// </summary>
            /// <param name="obj">能序列化的对象</param>
            /// <returns></returns>
            public static byte[] ObjectToBytes(object obj)
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    IFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(ms, obj);
                    return ms.GetBuffer();
                }
            }        /**/
            /// <summary>
            /// 将一个序列化后的byte[]数组还原
            /// </summary>
            /// <param name="Bytes"></param>
            /// <returns></returns>
            public static object BytesToObject(byte[] Bytes)
            {
                using (MemoryStream ms = new MemoryStream(Bytes))
                {
                    IFormatter formatter = new BinaryFormatter();
                    return formatter.Deserialize(ms);
                }
            }        public static void save(string Path, object SenderFile)
            {
                byte[] tempdata = ObjectToBytes(SenderFile);
                File.WriteAllBytes(Path, tempdata);
            }        public static object inputfile(string Path)
            {
                byte[] tempdata = File.ReadAllBytes(Path);
                return BytesToObject(tempdata);
            }
    类似这种?
      

  8.   

    利用泛型可以实现任意实体的读取与写入,一般都是用在与DB作交互时比较方便,实体类保存也可以进行序列号后写入xml文件保存
      

  9.   

    一个数据库对象,才会有Save功能。例如public class MyDB
    {
        public void Save<T>(T obj)
        {
              ......
        }
       
        ........
    }这其实就是 ORM!或者看看你的 vs 里的 EF 工具也是如此。(只不过 EF 接口不如自己开发的 ORM 更好用而已)
      

  10.   


    至少有两种写法。一种是可以采用基于反射的做法。例如public void Save<T>(T obj)
    {
        FieldInfo[] fs = typeof(T).GetFields();
        Dictionary<string, object> dic = new Dictionary<string, object>();
        foreach (var f in fs)
            dic.Add(f.Name, f.GetValue(obj));
        找到 fs 中名为 ID 的属性作为主键_保存数据到数据库(dic);
    }这里,实际上仅需要执行一次 GetFields ,然后把 fs 就缓存起来。而不需要每一次对同一类型对象执行Save时都反射一次。另外一种,就像 EF 一样,在vs上开发一个插件,预先自动对用户代码进行语法分析并且产生"针对每一个类型的单独的Save方法代码“,例如假设生成的隐藏代码的方法(委托)放在一个 SaveMethods<string, Action<object>> 集合中,那么Save方法就可以写为public void Save<T>(T obj)
    {
        string name = typeof(T).FullName;
        SaveMethods[name](obj);
    }
      

  11.   

    注意,并不是实体对象有Save方法。那种设计是错误的!实体不能够具有Save功能。一个对象容器,例如数据库,才有Save功能。它能够把多个对象保存起来,甚至可以保存不同种类的对象集合。实体自己不会知道如何 Save 的。不同的程序员实例化不同的数据容器,针对同一个实体可以执行不同的 Save 功能,把同一个实体保存到不同种类的数据库中。“数据库”我们采取比较宽泛的定义,即使针对“云”的存储机制我们也可以叫做数据库。但是一般来说,数据库系统最关键地是“查询效率”问题,因为这会影响程序数万倍查询效率!如果你只是想到了把数据实体能够简单保存,那么可能是不实用的。因此通常我们都是实现一个Save函数,它把任意实体对象保存到关系数据库中(例如SQL Server),先实现针对关系数据库的保存,然后扩展为通用化的Save接口。而如果仅仅是保存json、xml格式的文本文件,根本不做这种通用化的Save。另外就是要考虑“多态”问题。例如我上面写的这个Save就不支持多态(假设你声明  Person x = new Pregnant(),那么只能保存 Person 的内容,不能保存 Pregnant 的扩展内容)。也许你要实现的是需要支持多态的,那么就应该重新设计上述函数。通用查询也是一样。如果你自己设计的通用查询函数public IQueryable<T> Query<T>()
    {
          ....
    }它支持使用者使用标准的LINQ语法来编写查询语句(你的这个Query<T>函数会自动产生数据库原生查询语句并延迟查询),你也可能需要考虑是否支持多态的问题。比如说用户写var result = from x in Person
               where x.City == "成都"
               select x;这时候你需要考虑假设某个 Person 实例当初 Save(obj) 的时候其实是作为 Pregnant 实体保存的,那么此时是否应该在Person集合中包括一个 Pregnant 实体呢?
      

  12.   


    如何保存任意实体,就好像在问:如何打造一把万能锁钥1.如楼上所说的,每个实体类中,自定义save方法,通过实体.save()调用。
    2.还是要每个实体类中,自定义save方法。但是:使用简单工厂模式,在工厂中进行判断(用switch语句枚举判断。可以使用反射机制加速效率),并在工厂中实现实体.save()调用。客户端只需要
    Factory.Save(ProductInfo);
    Factory.Save(OrderInf9);

    就可以保存相应的实体。
    以此隐藏save方法的细节。这个好,有借鉴的代码不?
      

  13.   


    这个好,有借鉴的代码不?这是设计模式入门的基础知识,其实效率并不高。
    大话设计模式//简单运算工厂类
    public class OperationFactory {
        public static Operation createOperate(String operate)
        {
            Operation oper=null;
            switch(operate)
            {
                case "+":
                    oper=new OperationAdd();
                    break;
                case "-":
                    oper=new OperationSub();
                    break;
                case "*":
                    oper=new OperationMul();
                    break;
                case "/":
                    oper=new OperationDiv();
                    break;
            }
            return oper;
        }   
    }
    从核心代码可以看到,里面只是简单的switch遍历,效率不高,使用反射可以改进。
      

  14.   


    请教大神,评价下这样的设计,这是基于三层架构开发的,定义了实体类、实体的抽象接口类、实体的逻辑处理类;扫下盲哈:namespace GIS.Model
    {
    /// <summary>
    /// Sys_Department:实体类(属性说明自动提取数据库字段的描述信息)
    /// </summary>
    [Serializable]
    public partial class Sys_Department
    {
    public Sys_Department()
    {}
    #region Model
    private int _dept_id;
    private string _up_dept_id;
    private string _dept_name;
    private string _dept_desc;
    private decimal? _sort;
    /// <summary>
    /// 
    /// </summary>
            public int DEPT_ID
    {
    set{ _dept_id=value;}
    get{return _dept_id;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string UP_DEPT_ID
    {
    set{ _up_dept_id=value;}
    get{return _up_dept_id;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string DEPT_NAME
    {
    set{ _dept_name=value;}
    get{return _dept_name;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string DEPT_DESC
    {
    set{ _dept_desc=value;}
    get{return _dept_desc;}
    }
    /// <summary>
    /// 
    /// </summary>
    public decimal? SORT
    {
    set{ _sort=value;}
    get{return _sort;}
    }
    #endregion Model }
    }
    using System;
    using System.Data;
    namespace GIS.IDAL
    {
    /// <summary>
    /// 接口层Sys_Department
    /// </summary>
    public interface ISys_Department
    {
    #region  成员方法
    /// <summary>
    /// 是否存在该记录
    /// </summary>
    bool Exists(string DEPT_ID);
    /// <summary>
    /// 增加一条数据
    /// </summary>
    bool Add(GZPI.GZDX.GISPortal.Model.Sys_Department model);
    /// <summary>
    /// 更新一条数据
    /// </summary>
    bool Update(GZPI.GZDX.GISPortal.Model.Sys_Department model);
    /// <summary>
    /// 删除一条数据
    /// </summary>
    bool Delete(string DEPT_ID);
    bool DeleteList(string DEPT_IDlist );
    /// <summary>
    /// 得到一个对象实体
    /// </summary>
    GZPI.GZDX.GISPortal.Model.Sys_Department GetModel(string DEPT_ID);
    /// <summary>
    /// 获得数据列表
    /// </summary>
    DataSet GetList(string strWhere);
    /// <summary>
    /// 根据分页获得数据列表
    /// </summary>
    //DataSet GetList(int PageSize,int PageIndex,string strWhere);
    #endregion  成员方法

    }=
    namespace GIS.BLL
    {
    /// <summary>
    /// Sys_Department
    /// </summary>
    public partial class Sys_Department
    {
    private readonly ISys_Department dal=DataAccess.CreateSys_Department();
    public Sys_Department()
    {}
    #region  Method
    /// <summary>
    /// 是否存在该记录
    /// </summary>
    public bool Exists(string DEPT_ID)
    {
    return dal.Exists(DEPT_ID);
    } /// <summary>
    /// 增加一条数据
    /// </summary>
    public bool Add(GIS.Model.Sys_Department model)
    {
    return dal.Add(model);
    } /// <summary>
    /// 更新一条数据
    /// </summary>
    public bool Update(GIS.Model.Sys_Department model)
    {
    return dal.Update(model);
    }    .......省略.....
    #endregion  Method
    }
    }
      

  15.   


    请教大神,评价下这样的设计,这是基于三层架构开发的,定义了实体类、实体的抽象接口类、实体的逻辑处理类;扫下盲哈:namespace GIS.Model
    {
    /// <summary>
    /// Sys_Department:实体类(属性说明自动提取数据库字段的描述信息)
    /// </summary>
    [Serializable]
    public partial class Sys_Department
    {
    public Sys_Department()
    {}
    #region Model
    private int _dept_id;
    private string _up_dept_id;
    private string _dept_name;
    private string _dept_desc;
    private decimal? _sort;
    /// <summary>
    /// 
    /// </summary>
            public int DEPT_ID
    {
    set{ _dept_id=value;}
    get{return _dept_id;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string UP_DEPT_ID
    {
    set{ _up_dept_id=value;}
    get{return _up_dept_id;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string DEPT_NAME
    {
    set{ _dept_name=value;}
    get{return _dept_name;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string DEPT_DESC
    {
    set{ _dept_desc=value;}
    get{return _dept_desc;}
    }
    /// <summary>
    /// 
    /// </summary>
    public decimal? SORT
    {
    set{ _sort=value;}
    get{return _sort;}
    }
    #endregion Model }
    }
    using System;
    using System.Data;
    namespace GIS.IDAL
    {
    /// <summary>
    /// 接口层Sys_Department
    /// </summary>
    public interface ISys_Department
    {
    #region  成员方法
    /// <summary>
    /// 是否存在该记录
    /// </summary>
    bool Exists(string DEPT_ID);
    /// <summary>
    /// 增加一条数据
    /// </summary>
    bool Add(GZPI.GZDX.GISPortal.Model.Sys_Department model);
    /// <summary>
    /// 更新一条数据
    /// </summary>
    bool Update(GZPI.GZDX.GISPortal.Model.Sys_Department model);
    /// <summary>
    /// 删除一条数据
    /// </summary>
    bool Delete(string DEPT_ID);
    bool DeleteList(string DEPT_IDlist );
    /// <summary>
    /// 得到一个对象实体
    /// </summary>
    GZPI.GZDX.GISPortal.Model.Sys_Department GetModel(string DEPT_ID);
    /// <summary>
    /// 获得数据列表
    /// </summary>
    DataSet GetList(string strWhere);
    /// <summary>
    /// 根据分页获得数据列表
    /// </summary>
    //DataSet GetList(int PageSize,int PageIndex,string strWhere);
    #endregion  成员方法

    }=
    namespace GIS.BLL
    {
    /// <summary>
    /// Sys_Department
    /// </summary>
    public partial class Sys_Department
    {
    private readonly ISys_Department dal=DataAccess.CreateSys_Department();
    public Sys_Department()
    {}
    #region  Method
    /// <summary>
    /// 是否存在该记录
    /// </summary>
    public bool Exists(string DEPT_ID)
    {
    return dal.Exists(DEPT_ID);
    } /// <summary>
    /// 增加一条数据
    /// </summary>
    public bool Add(GIS.Model.Sys_Department model)
    {
    return dal.Add(model);
    } /// <summary>
    /// 更新一条数据
    /// </summary>
    public bool Update(GIS.Model.Sys_Department model)
    {
    return dal.Update(model);
    }    .......省略.....
    #endregion  Method
    }
    }一个好的 DAL 框架应该跟具体某个业务实体没有什么关系。你在 DAL 里边纠结什么 Department 等等,那么你的 DAL 一定是一大堆、比100年前老太太的裹脚布还要长、还要味道不好的代码。一个 DAL 框架的代码应该专业,针对数据库操作。有些人从微软10几年前坑爹的 PetShop 中学来的所谓 DAL,它纯粹是重复 BLL 层的东西。在 DAL 里围绕每一个业务对象去手工编写一堆千篇一律的代码,这充其量只应该是代码生成器来做的。更好的方法是连代码生成器都不要。如果手工写你这些代码,我觉得实在是还不如不搞编程这种低级工作。
      

  16.   

    许多人都会写简单的 SQLHelper,这算是一种 DAL 框架。但是它没有跟面向对象编程风格挂钩,它不能直接解析一个对象的增删改查,它只能处理你自己去写的 sql 语句。所以需要 ORM 系统来将关系数据库与面向对象的业务实体直接联系起来。也有些人使用 vs 内置的 EF。这是可以自动生成代码,将面向对象的实体与关系数据库联系起来。是一种官方的 ORM 框架。但是 EF 是基于代码生成机制的,它把自己跟业务实体紧紧捆绑起来了。它不能灵活地处理“任意一种”以前没有生成过代码、未知的 .net 类型。一个更好的 ORM系统,应该可以直接了当地把 .net 实体对象跟关系数据库联系起来。例如你写using(var db = new MySqlDBTransaction())
    {
        db.Save(obj1);
        foreach(var x in from a in db.Query<Person>()
                                  where a.City == "成都"
                                  select a)
        {
             x.City = "新成都";
             db.Save(x);
        }
        db.Commit();
    }类似于这样,一个 DAL 可以将“未知类型的”对象保存到对应的数据库中,并且可以查询,而不需要像 EF 那样需要繁琐的什么“视图定义、重建”等等一大堆复杂配置操作,那么就更方便。总之,DAL就是数据库驱动。只不过它跟 ADO.NET 的区别在于是否直接处理面向对象实体。而 PetShop 式的所谓 DAL,是画蛇添足,繁琐地增加没有技术含量的层次,很难说那种 DAL 到底有什么用。因为它不过是对 BLL 进行繁琐封装,而没有实现真正自成一体的、在你创建业务实体之前就创建了的通用 DAL 框架。
      

  17.   


    请教大神,评价下这样的设计,这是基于三层架构开发的,定义了实体类、实体的抽象接口类、实体的逻辑处理类;扫下盲哈:namespace GIS.Model
    {
    /// <summary>
    /// Sys_Department:实体类(属性说明自动提取数据库字段的描述信息)
    /// </summary>
    [Serializable]
    public partial class Sys_Department
    {
    public Sys_Department()
    {}
    #region Model
    private int _dept_id;
    private string _up_dept_id;
    private string _dept_name;
    private string _dept_desc;
    private decimal? _sort;
    /// <summary>
    /// 
    /// </summary>
            public int DEPT_ID
    {
    set{ _dept_id=value;}
    get{return _dept_id;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string UP_DEPT_ID
    {
    set{ _up_dept_id=value;}
    get{return _up_dept_id;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string DEPT_NAME
    {
    set{ _dept_name=value;}
    get{return _dept_name;}
    }
    /// <summary>
    /// 
    /// </summary>
    public string DEPT_DESC
    {
    set{ _dept_desc=value;}
    get{return _dept_desc;}
    }
    /// <summary>
    /// 
    /// </summary>
    public decimal? SORT
    {
    set{ _sort=value;}
    get{return _sort;}
    }
    #endregion Model }
    }
    using System;
    using System.Data;
    namespace GIS.IDAL
    {
    /// <summary>
    /// 接口层Sys_Department
    /// </summary>
    public interface ISys_Department
    {
    #region  成员方法
    /// <summary>
    /// 是否存在该记录
    /// </summary>
    bool Exists(string DEPT_ID);
    /// <summary>
    /// 增加一条数据
    /// </summary>
    bool Add(GZPI.GZDX.GISPortal.Model.Sys_Department model);
    /// <summary>
    /// 更新一条数据
    /// </summary>
    bool Update(GZPI.GZDX.GISPortal.Model.Sys_Department model);
    /// <summary>
    /// 删除一条数据
    /// </summary>
    bool Delete(string DEPT_ID);
    bool DeleteList(string DEPT_IDlist );
    /// <summary>
    /// 得到一个对象实体
    /// </summary>
    GZPI.GZDX.GISPortal.Model.Sys_Department GetModel(string DEPT_ID);
    /// <summary>
    /// 获得数据列表
    /// </summary>
    DataSet GetList(string strWhere);
    /// <summary>
    /// 根据分页获得数据列表
    /// </summary>
    //DataSet GetList(int PageSize,int PageIndex,string strWhere);
    #endregion  成员方法

    }=
    namespace GIS.BLL
    {
    /// <summary>
    /// Sys_Department
    /// </summary>
    public partial class Sys_Department
    {
    private readonly ISys_Department dal=DataAccess.CreateSys_Department();
    public Sys_Department()
    {}
    #region  Method
    /// <summary>
    /// 是否存在该记录
    /// </summary>
    public bool Exists(string DEPT_ID)
    {
    return dal.Exists(DEPT_ID);
    } /// <summary>
    /// 增加一条数据
    /// </summary>
    public bool Add(GIS.Model.Sys_Department model)
    {
    return dal.Add(model);
    } /// <summary>
    /// 更新一条数据
    /// </summary>
    public bool Update(GIS.Model.Sys_Department model)
    {
    return dal.Update(model);
    }    .......省略.....
    #endregion  Method
    }
    }我觉得结构还不错。从代码实现上说,使用提供基本 CRUD 的支持类模版的基类处理基本的数据存取操作可以减少大量的代码,我觉得可以使用 NHibernate 这是更成熟的产品。从设计模式上来讲,模型,基础架构和业务相互分离是很不错的,概念理解也是正确的,我觉得还需要 DataTransferObject 和一些 ObjectTranslator,把业务模型和数据模型区分开可以更好的解耦合
      

  18.   

    我分析了几个亲身经历的软件公司“为什么经过将近10年还是这种垃圾样子”的原因,对于那些技术含量不高的公司,扯这类过度的DAL然后貌似自己公司掌握了“三层”,这是一个主要原因。可能因为老板多年以前“迷上”了三层概念,可是以他的水平,即不能研究UI框架、也不能研发BLL工程方法,只有把虽有精力都用来追求尽量把DAL弄得繁琐一些、(貌似)什么设计都能做似地。以后再也没有做过什么实际的大点项目的开发工作了,于是对程序员的要求完全是复制他自己10年前那种概念。这种所谓的“三层”,看似可以方便地用来指责程序员们没有从csdn之类的地方学到什么“八股”知识,但是真的不能提高一个中小软件公司的实际的产品研发能力。因为它的精力的重点根本没有瞄准目标上。真正快速提高产品设计研发能力,需要把这种过分DAL概念抛弃掉,从实事求是的“开发效率”出发,仔细审查你所谓的“把业务模型和数据模型分离”的说法到底是浑浑噩噩模糊不清的还是可以就此为止不用再细研究了。目的是真正追求效率,而不是追求简单肤浅的理论。
      

  19.   

    没错,如果从头开始进行架构设计这样的成本是软件公司无法承受的,而像软件工厂似的使用两条流水线分别生产架构和产品也是中小型软件企业无法承受的,所以才会有很多开源的框架或软件产品帮助开发人员更多的关注业务而不是基础架构。这样可以帮助企业快速的开发高质量的产品。例如楼上朋友所说 DAL 抛弃掉,我们可以通过使用其他产品替代自己的从头开发而不是把这些代码和其他逻辑混杂起来,这样我们不仅保持了更好的软件架构,更好的易用性和可扩展性并且减少了成本。当然这意味着你在做一个软件产品,而不是一次性的软件。
      

  20.   


    感谢大神指点!!
    这样的DAL设计是微软很早之前提出的,对于新人来说,那个petshop的例子的确很有学习意义。我个人觉得,虽然这种设计虽然有点冗余过时,而且有很多更好更高效率简洁的架构可以使用,但是我们应该理解这种设计的优点和缺点,这样我们更能明白ORM系统的精华所在。不断学习进步,方能走得更远!