yet

Dream Will Come True

 

利用SQL2005的forxml以及反系列化去替代ORM?

   ORM用多了就会发现越来越多的问题。。。。。最后就觉得ORM简直是鸡肋....(呵呵,别拿砖头砸我,个人觉得而已)
   最后没办法了,发现SQL2005出来一个for xml 可以直接将查询生成xml返回,如果能把这个返回来的xml直接反系列化成实体,貌似很可爱,在测试了一段时间后决定把它用到项目中去。项目完成用到现在为止还没出现过严重问题,看来这个解决方案是可行的,不敢独享,贴出来大家一起讨论讨论。
   一。在使用过程中,遇到过以下几个问题:
   1、编写查询的存储过程是比较麻烦的(为此专门写了个windows小工具来辅助生成查询)
   2、实体名不能随便改。。。。跟查询的存储过程有联系(这个就没办法了,反正实体名我不改就是了)
   3、xml非法字符问题。(替换。。。)
   4、xml中带有html字符的时候(cdata,然而怎么在数据库查询的是偶构建cdata字段的问题)
   5、好像没再遇到什么问题了,至于有人说大量查询的时候会出现xml断层的问题也是比较容易解决的
   二。至于效率问题的话,现在这个项目网站运行差不多一个月来有12000用户注册,不见有任何服务器CPU过高或者死机的情况(当然这跟数据库存储过程优化以及数据库索引有很大关系),算是比较满意。
   三。详细解决方案
    1、数据库方面
    当然不能再用SELECT * FROM 什么的方法了。下面是一个简单的查询
a、返回数据集
SELECT
 1    as Tag,
 0    as Parent,
 UserId as [Users!1!UserId!ELEMENT],--用户ID
 UserEmail as [Users!1!UserEmail!cdata] --用户Email
 FROM
 [User]
 FOR XML EXPLICIT,ROOT('ArrayOfUser')

b、返回单条数据
SELECT
 1    as Tag,
 0    as Parent,
 UserId as [Users!1!UserId!ELEMENT],--用户ID
 UserEmail as [Users!1!UserEmail!cdata] --用户Email (注意,这里使用cdata就可以把生成的xml文件UserEmail包含在cdata中)
 FROM
 [User] WHERE UserId = 1
 FOR XML EXPLICIT
    2、程序方面
   呵,不像一些ORM框架一样要引入项目,生成配置文件这么痛苦~~换来的是要自己写sqlcommand,open sqlconnection等等,但是我个人认为这些东西自己写的话也有很多方法可以偷懒,呵呵在这里就不介绍这些东西了,反正创建一个SQLCOMMAND,给SQLCOMMAND提供相应的参数,然后SQLCOMMAND.ExecuteDataReader就好了。。。
   a、当然你的有个User的实体,大概如下:
public class User
{
    int userId = 0;
    public int UserId
    {
        get{}
        set{}
    }
    //略
}
   b、然后你必须将上面的存储过程执行,并返回datareader
   c、反序列化
 private static Regex reg = new Regex("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]", RegexOptions.Compiled| RegexOptions .IgnoreCase | RegexOptions.Multiline);
        
/// <summary>
        
/// 反序列化对象
        
/// </summary>
        
/// <param name="xmlstr">源xml字符串</param>
        
/// <param name="objtype">要序列化后的类型</param>
        
/// <returns>结果</returns>

        static public object Deserialize(string xmlstr, Type objtype)
        
{
            
if (string.IsNullOrEmpty(xmlstr))
                
return null;
            
object obj = null
            xmlstr 
= reg.Replace(xmlstr, "");
            
            XmlSerializer serializer 
= new XmlSerializer(objtype);
            
try
            
{
                obj 
= serializer.Deserialize(new StringReader(xmlstr));
            }

            
catch {
                xmlstr 
= xmlstr.Replace("&""&amp;");
                obj 
= serializer.Deserialize(new StringReader(xmlstr));
            }

            
return obj;
        }
 
        
/// <summary>
        
/// 反序列化对象
        
/// </summary>
        
/// <param name="reader">从reader进行反序列化,序列化完毕后将在这里关闭</param>
        
/// <param name="objtype">要序列化后的类型</param>
        
/// <returns>结果</returns>

        static public object Deserialize(System.Data.IDataReader reader, Type objtype)
        
{
            
return Deserialize(reader, objtype, true);
        }

        
/// <summary>
        
/// 反序列化对象
        
/// </summary>
        
/// <param name="reader">从reader进行反序列化,序列化完毕后将在这里关闭</param>
        
/// <param name="objtype">要序列化后的类型</param>
        
/// <param name="isCloseReader">是否关闭IDataReader</param>
        
/// <returns>结果</returns>

        static public object Deserialize(System.Data.IDataReader reader, Type objtype,bool isCloseReader)
        
{
            StringBuilder sb 
= new StringBuilder();
            
while (reader.Read())
                sb.Append(reader[
0].ToString());
            
if(isCloseReader)
                reader.Close();
           
            
try
            
{
                
return Deserialize(sb.ToString(), objtype);
            }

            
catch (Exception ex)
            
{
                
throw;
            }

        }

d、将你执行后的datareader直接调用上面的方法

User user = Deserialize(reader,typeof(User));
或者
User[] user = Deserialize(reader,typeof(User[]));
 
======================================end===========================================
就是这么简单。。。。至于说那些什么反射啊之类的影响性能啊(个人觉得在.NET里面的性能就算再优化,还不如花多点时间去优化SQL查询语句以及SQL数据库索引)。。还是看具体的结果去检验吧
其它就待补~~~没时间再写了。。呵呵

  

posted on 2007-10-24 15:38  yet  阅读(2081)  评论(22编辑  收藏  举报

导航