惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

博客园 - 阿牛-专注金融行业开发

2014-09-19.xml ADO.NET 3.5高级编程:应用LINQ&Entity Framework C#高级编程(第8版) ASP.NET MVC 4 Web编程 Version of SQLCE in WP8 Lesson 9 Oral English Training: Lesson 7 一个不错的Options交易策略网"option trading tips"可以学到各种Options的定义. 加强金融专业知识学习,现实从代码开发到业务设计的转型 SOA不是Web Service ReportViewer使用手册 梳理一下最近要重点好学的东西 有空看完<Beginning Xml with C# 2008>这本书, 深入学习一下Xml. Java vs C# 命名规则 <.NET分布式应用程序开发>读书笔记 第十章:Q&A Ndo v3.1发布了! ODP.NET和System.Data.OracleClient的一些不同 Singleton设计模式活学活用: 请求单一 vs 线程单一 Table Scan, Index Scan, Index Seek
手动建立强类型DataSet
阿牛-专注金融行业开发 · 2009-11-27 · via 博客园 - 阿牛-专注金融行业开发

问:为不什么不用VS自动建立的DataSet?

答:VS自动建立的DataSet有如下不足, 所以我不用. 喜欢代码完全由自己掌控的感觉:)

(1)代码繁杂. 共有四个文件,很多时候,我们只需要 DataSet的类型定义

(2)不支持空值, 如果有空值,会引发异常.我检查了它的代码, 它没有检查是不是DBNull.Value,是直接转型的.

(3)和底层数据库有耦合, 你生成时连接什么数据库, 它生成的Connection, DataAdapter, Command就是什么类型的. SQL语句也是写死的.

(提示:VS2008有一个功能是将DataSet定义和数据访问的代码分开, 不过DataSet的代码也有一大堆)

下面是我自己建立的DataSet, 支持数据绑定, Linq To DataSet. 支持空值.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Collections;
using System.Runtime.Serialization;
using System.Xml;
using System.IO;

namespace UnitTest
{
    /// <summary>
    /// Typed Data Set prototype
    /// </summary>
    public class MyDataSet : DataSet
    {
        public MyDataSet()
            : base()
        {
            this.BeginInit();
            this.InitClass();
            this.EndInit();

        }

#if Serialization //For serialization use only, can be remove        
        protected MyDataSet(SerializationInfo info, StreamingContext context) : 
                base(info, context, false) {
            if ((this.IsBinarySerialized(info, context) == true)) {
                this.InitVars(false);                
                return;
            }
            string strSchema = ((string)(info.GetValue("XmlSchema", typeof(string))));
            if ((this.DetermineSchemaSerializationMode(info, context) == global::System.Data.SchemaSerializationMode.IncludeSchema)) {
                DataSet ds = new DataSet();
                ds.ReadXmlSchema(new XmlTextReader(new StringReader(strSchema)));
                if ((ds.Tables["Person"] != null)) {
                    base.Tables.Add(new PersonDataTable(ds.Tables["Person"]));
                }
              
                this.DataSetName = ds.DataSetName;
                this.Prefix = ds.Prefix;
                this.Namespace = ds.Namespace;
                this.Locale = ds.Locale;
                this.CaseSensitive = ds.CaseSensitive;
                this.EnforceConstraints = ds.EnforceConstraints;
                this.Merge(ds, false, global::System.Data.MissingSchemaAction.Add);
                this.InitVars();
            }
            else {
                this.ReadXmlSchema(new global::System.Xml.XmlTextReader(new global::System.IO.StringReader(strSchema)));
            }
            this.GetSerializationData(info, context);            
        }

        private void InitVars()
        {
            InitVars(true);
        }

        private void InitVars(bool initTable)
        {
            _personTable = ((PersonDataTable)(base.Tables["Person"]));
            if ((initTable == true))
            {
                if ((_personTable != null))
                {
                    _personTable.InitVars();
                }
            }
        }
#endif
        private void InitClass()
        {
            _personTable = new PersonDataTable();
            base.Tables.Add(_personTable);
            this.DataSetName = "MyDataSet";
        }

        private PersonDataTable _personTable;

        public PersonDataTable PersonTable
        {
            get { return _personTable; }          
        }

        public class PersonDataTable : TypedTableBase<PersonRow>//For .NET 3.5
        //public class PersonDataTable : DataTabe //For .NET 2.0
        {
            public PersonDataTable()
                : base()
            {
                this.BeginInit();
                this.InitClass();
                this.EndInit();
            }
#if Serialization
            internal PersonDataTable(DataTable table)
            {
                this.TableName = table.TableName;
                if ((table.CaseSensitive != table.DataSet.CaseSensitive)) {
                    this.CaseSensitive = table.CaseSensitive;
                }
                if ((table.Locale.ToString() != table.DataSet.Locale.ToString())) {
                    this.Locale = table.Locale;
                }
                if ((table.Namespace != table.DataSet.Namespace)) {
                    this.Namespace = table.Namespace;
                }
                this.Prefix = table.Prefix;
                this.MinimumCapacity = table.MinimumCapacity;
            }
#endif
            //Key 1
            private void InitClass()
            {
                this.TableName = "Person";
                _idColumn = new DataColumn("ID", typeof(Int32));                
                _idColumn.AllowDBNull = false;
                _idColumn.AutoIncrement = true;
                _idColumn.ReadOnly = true;
                _idColumn.Unique = false;                
                this.Columns.Add(_idColumn);

                this.Constraints.Add(new UniqueConstraint("PK",
                    new DataColumn[] { this._idColumn }, true));
                

                _nameColumn = new DataColumn("Name", typeof(String));
                _nameColumn.AllowDBNull = false;
                this.Columns.Add(_nameColumn);

                _ageColumn = new DataColumn("Age", typeof(Int32));
                _ageColumn.AllowDBNull = false;
                this.Columns.Add(_ageColumn);

                _dtColumn = new DataColumn("DT", typeof(DateTime));
                _dtColumn.AllowDBNull = true;
                this.Columns.Add(_dtColumn);     

            }

            //For xml serizeler
            internal void InitVars()
            {
                this._idColumn = base.Columns["Id"];
                this._nameColumn = base.Columns["Name"];
                this._ageColumn = base.Columns["Age"];
                this._ageColumn = base.Columns["DT"];
            }

            public PersonRow NewPersonRow()
            {
                return (PersonRow)this.NewRow();
            }
            //Key 2
            protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
            {
                return new PersonRow(builder);
            }

            public void RemovePersonRow(PersonRow row)
            {
                this.Rows.Remove(row);
            }

            //Key 3
            protected override Type GetRowType()
            {
                return typeof(PersonRow);
            }
            
            private DataColumn _idColumn;

            public DataColumn IdColumn
            {
                get { return _idColumn; }              
            }
            private DataColumn _nameColumn;

            public DataColumn NameColumn
            {
                get { return _nameColumn; }               
            }
            private DataColumn _ageColumn;

            public DataColumn AgeColumn
            {
                get { return _ageColumn; }
            }

            private DataColumn _dtColumn;
            public DataColumn DTColumn
            {
                get { return _dtColumn; }
            }

            public long Count
            {
                get
                {
                    return this.Rows.Count;
                }
            }

            public PersonRow this[int index]
            {
                get
                {
                    return ((PersonRow)(this.Rows[index]));
                }
            }

            public void AddPersonRow(PersonRow newRow)
            {
                this.Rows.Add(newRow);
            }

            public PersonRow FindByID(int id)
            {
                return ((PersonRow)(this.Rows.Find(new object[] {
                            id})));
            }

            //Key 4
            protected override DataTable CreateInstance()
            {
                return new PersonDataTable();
            }
        }        
        
        public class PersonRow : DataRow
        {
            internal PersonRow(DataRowBuilder builder)
                : base(builder)
            {
                this._table = ((PersonDataTable)(this.Table));
            }

            public override string ToString()
            {
                return string.Format("<{0}>|Id={1},Age={2},Name={3},DT={4}", this._table.TableName, ID, Age, Name, DT);
            }

            private PersonDataTable _table;
            
            public int ID
            {
                get { return (int)this[_table.IdColumn]; }
                set { this[_table.IdColumn] = value; }
            }
            
            public string Name
            {
                get
                {
                    if (this[_table.NameColumn]==DBNull.Value)
                    {
                        return "";
                    }
                    return (string)this[_table.NameColumn];
                }
                set { this[_table.NameColumn] = value; }
            }
            
            public int Age
            {
                get
                {
                    if (this[_table.AgeColumn] == DBNull.Value)
                    {
                        return -1;
                    }
                    return (int)this[_table.AgeColumn];
                }
                set { this[_table.AgeColumn] = value; }
            }

            public DateTime? DT
            {
                get
                {
                    if (this[_table.DTColumn] == DBNull.Value)
                    {
                        return null;
                    }
                    return (DateTime)this[_table.DTColumn];
                }
                set
                {
                    if (value == null)
                        this[_table.DTColumn] = DBNull.Value;
                    else
                        this[_table.DTColumn] = value;
                }
            }
        }

        private void InitializeComponent()
        {
            ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
            // 
            // MyDataSet
            // 
            this.DataSetName = "MyDataSet";
            ((System.ComponentModel.ISupportInitialize)(this)).EndInit();

        }    
    
    }

  
}

单元测试:

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using System.Data.SqlClient;
using System.Data;
using System.Data.Common;

namespace UnitTest
{
    [TestFixture]
    
    public class MyDataSetTest  
    {
        public MyDataSetTest()
            : base()
        { }

        private SqlConnection _conn;
        private SqlDataAdapter _adp;
        [SetUp]
        public void Setup()
        {
            _conn = new SqlConnection("Data Source=192.168.5.99;Initial Catalog=NDO_TEST_V31;User ID=sa;….");
            _adp = new SqlDataAdapter("select ID, Name, Age,DT from Person", _conn);

            DataTableMapping dtm = new DataTableMapping("Table", "Person");
            dtm.ColumnMappings.Add(new DataColumnMapping("ID", "ID"));
            dtm.ColumnMappings.Add(new DataColumnMapping("Name", "Name"));
            dtm.ColumnMappings.Add(new DataColumnMapping("Age", "Age"));
            dtm.ColumnMappings.Add(new DataColumnMapping("DT", "DT"));
            _adp.TableMappings.Add(dtm);


            //For update data
            SqlCommandBuilder cb = new SqlCommandBuilder(_adp);
            _adp.UpdateCommand = cb.GetUpdateCommand();
            SqlCommand cmd = cb.GetInsertCommand();
            _adp.InsertCommand = new SqlCommand(cmd.CommandText);
            for (int i = 0; i < cmd.Parameters.Count; i++)
            {
                _adp.InsertCommand.Parameters.Add(cmd.Parameters[i].ParameterName, cmd.Parameters[i].SqlDbType, cmd.Parameters[i].Size, cmd.Parameters[i].SourceColumn);

            }
            _adp.DeleteCommand = cb.GetDeleteCommand();
            _adp.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;

            Console.WriteLine(_adp.InsertCommand.CommandText);
            _adp.InsertCommand.CommandText = _adp.InsertCommand.CommandText + "; SELECT SCOPE_IDENTITY() as ID";
            Console.WriteLine(_adp.InsertCommand.CommandText);

        }

        [TearDown]
        public void ShutDown()
        {
            _conn.Close();
            _conn.Dispose();
        }
        [Test]
        public void Fill()
        {
            MyDataSet ds = new MyDataSet();
            Console.WriteLine("Filling data set...");
            _adp.Fill(ds);

            Assert.IsNotNull(ds.PersonTable);
            Assert.AreEqual(true, ds.PersonTable.Count > 0);
            Console.WriteLine("Row count: {0}", ds.PersonTable.Rows.Count);
        
        }

        [Test]
        public void LinqQuery()
        {
            MyDataSet ds = new MyDataSet();
            Console.WriteLine("Filling data set...");
            _adp.Fill(ds);

            Assert.IsNotNull(ds.PersonTable);
            Assert.AreEqual(true, ds.PersonTable.Count > 0);
            Console.WriteLine("Row count: {0}", ds.PersonTable.Rows.Count);

            var query = from n in ds.PersonTable
                        where n.Age > 100
                        orderby n.Age descending
                        select n;
            foreach (var item in query)
            {
                Console.WriteLine(item);
            }            
        }

        [Test]
        public void AddUpdateDelete()
        {
            MyDataSet ds = new MyDataSet();
            Console.WriteLine("Filling data set...");
            _adp.Fill(ds);

            Assert.IsNotNull(ds.PersonTable);
            Assert.AreEqual(true, ds.PersonTable.Count > 0);
            Console.WriteLine("Row count: {0}", ds.PersonTable.Rows.Count);       

            MyDataSet.PersonRow r = ds.PersonTable.NewPersonRow();            
            r.Name = "ROCK";
            r.Age = DateTime.Now.Millisecond;
            r.DT = DateTime.Now;

            ds.PersonTable.AddPersonRow(r);

            MyDataSet.PersonRow r2 = ds.PersonTable.NewPersonRow();            
            r2.Name = "ROCK2";
            r2.Age = DateTime.Now.Millisecond;
            r2.DT = null;

            ds.PersonTable.AddPersonRow(r2);
            Console.WriteLine("Delete 1st row");
            ds.PersonTable.Rows[0].Delete();
            Console.WriteLine("Update 2nd row'Age to 99999");
            ds.PersonTable[1].Age = 99999;

            int k = _adp.Update(ds);            
            Assert.AreEqual(4, k);

            Assert.AreEqual(99999, ds.PersonTable[0].Age);

            Assert.AreEqual(true, r.ID > 0);
            Console.WriteLine("New row#1 id:{0}", r.ID);
            Assert.AreEqual(true, r2.ID > 0);            
            Console.WriteLine("New row#2 id:{0}", r2.ID);

            MyDataSet.PersonRow r2copy = ds.PersonTable.FindByID(r2.ID);
            Assert.AreEqual(true, Object.ReferenceEquals(r2copy, r2));
            Console.WriteLine(r2copy);            

        }    
    }
}