未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值。

问题未解决

 Strongly Typed DataSet 优缺点

使用强类型DataSet

MyCustomers myCustomers=new MyCustomers();

MyCustomers.CustomersDataTable tblCustomers= myCustomers.Customers;

MyCustomers.CustomersRow rowCustomers=tblCustomers.NewCustomersRow();

rowCustomers.XXX=xxx;

//.

tblCustomers.AddCustomersRow(rowCustomers);

结合vs.net的自动完成功能可以大大提高开发效率。

强类型DataSet优缺点

优点:

1)  设计时的优势,编写代码容易,能够充分利用vs.net的自动完成功能

2)  能更容易地在设计时绑定控件

3)  运行时可以提高应用程序的性能
这主要是因为在访问某条记录的某个字段时,使用DataColumn对象本身比使用列名具有更高的效率,但增加了维护的困难。强类型的DataSet替我们解决了这个问题。

缺点:

不灵活。

1)  因为架构信息已经硬编码进MyCustomers.cs,如果发生改动的话,必须重新生成。

2)  比如从拥有30个字段的某个表中选择3个字段ABC,专门为这三个字段生成一个强类型的DataSet1是可以的,但是倘若另一个方法需要选择字段CDE,还需要为这三个字段专门生成一个强类型的DataSet2。倘若select的字段由使用者自行定制,字段的一个组合就了不得了。

3)  为避免上面使用多个强类型DataSet的情况,我们可以只使用一个强类型DataSet,这样每次不管我们Fill多少个字段,都填充进一个强类型DataSet
但这又带来了新的问题:
i)
空间的浪费(特别是对于多表连接的情况)。可以写代码测试一下30string字段中只填充12个占用的空间相对大小(使用强类型DataSet比弱类型占用内存大数倍不止)。
ii)
约束的违反。强类型在生成时已经把数据库中的约束(如非空,FK等)添加了进来,这样在只填充部分数据时可能会发生违反约束的异常。
比如col1,col2,col3,col4都要求不为空,但是我只selectcol1col2进入强类型DataSet,这样对应记录的col3col4字段均为空,违反了非空约束,会抛出异常并提示:
未处理的“System.Data.ConstraintException”类型的异常出现在 system.data.dll 中。

其他信息: 未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值。

尽管可以设置DataSetEnforceConstraints属性,但是用起来还是不爽。

 

所以,强弱类型DataSet恐怕还得结合着用,或者放弃使用强类型DataSet

23:41 | 评论 (0)

Strongly Typed DataSet(2) ——生成代码分析

生成代码分析

生成示例DataSet

MicrosoftNorthwind的表Customers为例生成一个强类型的DataSet:

1)新建一个DataAdapter,使用的sql语句为

select * from Customers

2)使用该DataAdapter建立数据集MyCustomers

2.2.2 查看代码

我们可以发现,vs.net添加了一个MyCustomers.xsd文件,如果选择查看所有文件,还可以看到对应有一个MyCustomers.cs文件。

//MyCustomers.cs

1)定义了一个继承自DataSet的类MyCustomers

除了定义2),3),4)中的类外,主要是维护了一个对tableCustomers的引用

 

2MyCustomers中定义了继承自DataTable的类CustomersDataTable

        public class CustomersDataTable : DataTable, System.Collections.IEnumerable {

            //为每个字段定义了相应的DataColumn对象,通过属性访问。使用DataColumn可以提高访问效率

            private DataColumn columnCustomerID;

            private DataColumn columnCompanyName;

            private DataColumn columnContactName;

            private DataColumn columnContactTitle;

            //其他字段的DataColumn对象

           

            internal CustomersDataTable() :

                    base("Customers") {

                this.InitClass();

            }

           

            internal CustomersDataTable(DataTable table) :

                    base(table.TableName) {

                //根据table设置本类的对应属性

                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;

                this.DisplayExpression = table.DisplayExpression;

            }

           

            [System.ComponentModel.Browsable(false)]

            //Count属性

            public int Count {

                get {

                    return this.Rows.Count;

                }

            }

           

            //上面各种DataColumn对应的属性

            internal DataColumn CustomerIDColumn {

                get {

                    return this.columnCustomerID;

                }

            }

           

            internal DataColumn CompanyNameColumn {

                get {

                    return this.columnCompanyName;

                }

            }

           

            internal DataColumn ContactNameColumn {

                get {

                    return this.columnContactName;

                }

            }

           

            internal DataColumn ContactTitleColumn {

                get {

                    return this.columnContactTitle;

                }

            }

           

            //索引,返回对应的CustomersRow

            public CustomersRow this[int index] {

                get {

                    return ((CustomersRow)(this.Rows[index]));

                }

            }

           

            public event CustomersRowChangeEventHandler CustomersRowChanged;

            public event CustomersRowChangeEventHandler CustomersRowChanging;

            public event CustomersRowChangeEventHandler CustomersRowDeleted;

            public event CustomersRowChangeEventHandler CustomersRowDeleting;

           

            //使用CustomersRow对象添加一行

            public void AddCustomersRow(CustomersRow row) {

                this.Rows.Add(row);

            }

            //使用各个字段的值填充一个新行

            public CustomersRow AddCustomersRow(string CustomerID, string CompanyName, string ContactName, string ContactTitle, string Address, string City, string Region, string PostalCode, string Country, string Phone, string Fax) {

                CustomersRow rowCustomersRow = ((CustomersRow)(this.NewRow()));

                rowCustomersRow.ItemArray = new object[] {//使用ItemArray属性设置CustomersRow的值

                        CustomerID,

                        CompanyName,

                        ContactName,

                        ContactTitle,

                        Address,

                        City,

                        Region,

                        PostalCode,

                        Country,

                        Phone,

                        Fax};

                this.Rows.Add(rowCustomersRow);

                return rowCustomersRow;

            }

            //通过CustomerID查找CustomersRow

            public CustomersRow FindByCustomerID(string CustomerID) {

                return ((CustomersRow)(this.Rows.Find(new object[] {

                            CustomerID})));

            }

            //返回Enumerator

            public System.Collections.IEnumerator GetEnumerator() {

                return this.Rows.GetEnumerator();

            }

            //Clone方法

            public override DataTable Clone() {

                CustomersDataTable cln = ((CustomersDataTable)(base.Clone()));

                cln.InitVars();

                return cln;

            }

            //创建新的实例

            protected override DataTable CreateInstance() {

                return new CustomersDataTable();

            }

            //DataColumn变量初始化函数,Clone()中调用,另一种调用方式是在MyCustomersInitVars()中调用

            internal void InitVars() {

                //各种DataColumn变量的初始化

                this.columnCustomerID = this.Columns["CustomerID"];

                this.columnCompanyName = this.Columns["CompanyName"];

                this.columnContactName = this.Columns["ContactName"];

                this.columnContactTitle = this.Columns["ContactTitle"];

                this.columnAddress = this.Columns["Address"];

                this.columnCity = this.Columns["City"];

                this.columnRegion = this.Columns["Region"];

                this.columnPostalCode = this.Columns["PostalCode"];

                this.columnCountry = this.Columns["Country"];

                this.columnPhone = this.Columns["Phone"];

                this.columnFax = this.Columns["Fax"];

            }

            //初始化函数,初始化Columns,并添加各种约束

            private void InitClass() {

                this.columnCustomerID = new DataColumn("CustomerID", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnCustomerID);

                this.columnCompanyName = new DataColumn("CompanyName", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnCompanyName);

                this.columnContactName = new DataColumn("ContactName", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnContactName);

                this.columnContactTitle = new DataColumn("ContactTitle", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnContactTitle);

                this.columnAddress = new DataColumn("Address", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnAddress);

                this.columnCity = new DataColumn("City", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnCity);

                this.columnRegion = new DataColumn("Region", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnRegion);

                this.columnPostalCode = new DataColumn("PostalCode", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnPostalCode);

                this.columnCountry = new DataColumn("Country", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnCountry);

                this.columnPhone = new DataColumn("Phone", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnPhone);

                this.columnFax = new DataColumn("Fax", typeof(string), null, System.Data.MappingType.Element);

                this.Columns.Add(this.columnFax);

                this.Constraints.Add(new UniqueConstraint("Constraint1", new DataColumn[] {

                                this.columnCustomerID}, true));

                this.columnCustomerID.AllowDBNull = false;

                this.columnCustomerID.Unique = true;

                this.columnCompanyName.AllowDBNull = false;

            }

           

            public CustomersRow NewCustomersRow() {

                return ((CustomersRow)(this.NewRow()));

            }

           

            protected override DataRow NewRowFromBuilder(DataRowBuilder builder) {

                return new CustomersRow(builder);

            }

           

            protected override System.Type GetRowType() {

                return typeof(CustomersRow);

            }

           

            protected override void OnRowChanged(DataRowChangeEventArgs e) {

                base.OnRowChanged(e);

                if ((this.CustomersRowChanged != null)) {

                    this.CustomersRowChanged(this, new CustomersRowChangeEvent(((CustomersRow)(e.Row)), e.Action));

                }

            }

           

            protected override void OnRowChanging(DataRowChangeEventArgs e) {

                base.OnRowChanging(e);

                if ((this.CustomersRowChanging != null)) {

                    this.CustomersRowChanging(this, new CustomersRowChangeEvent(((CustomersRow)(e.Row)), e.Action));

                }

            }

           

            protected override void OnRowDeleted(DataRowChangeEventArgs e) {

                base.OnRowDeleted(e);

                if ((this.CustomersRowDeleted != null)) {

                    this.CustomersRowDeleted(this, new CustomersRowChangeEvent(((CustomersRow)(e.Row)), e.Action));

                }

            }

           

            protected override void OnRowDeleting(DataRowChangeEventArgs e) {

                base.OnRowDeleting(e);

                if ((this.CustomersRowDeleting != null)) {

                    this.CustomersRowDeleting(this, new CustomersRowChangeEvent(((CustomersRow)(e.Row)), e.Action));

                }

            }

           

            public void RemoveCustomersRow(CustomersRow row) {

                this.Rows.Remove(row);

            }

        }

3MyCustomers中定义了继承自DataRow的类CustomersRow

        public class CustomersRow : DataRow {

            private CustomersDataTable tableCustomers;//保留了一个对DataTable的引用

            internal CustomersRow(DataRowBuilder rb) :

                    base(rb) {

                this.tableCustomers = ((CustomersDataTable)(this.Table));//初始化引用

            }

           

            public string CustomerID {

                get {

                    return ((string)(this[this.tableCustomers.CustomerIDColumn]));

                }

                set {

                    this[this.tableCustomers.CustomerIDColumn] = value;

                }

            }

           

            public string CompanyName {

                get {

                    return ((string)(this[this.tableCustomers.CompanyNameColumn]));

                }

                set {

                    this[this.tableCustomers.CompanyNameColumn] = value;

                }

            }

           

            public string ContactName {

                get {

                    try {

                        return ((string)(this[this.tableCustomers.ContactNameColumn]));

                    }

                    catch (InvalidCastException e) {

                        throw new StrongTypingException("无法获取值,因为它是 DBNull", e);

                    }

                }

                set {

                    this[this.tableCustomers.ContactNameColumn] = value;

                }

            }

           

            public string ContactTitle {

                get {

                    try {

                        return ((string)(this[this.tableCustomers.ContactTitleColumn]));

                    }

                    catch (InvalidCastException e) {

                        throw new StrongTypingException("无法获取值,因为它是 DBNull", e);

                    }

                }

                set {

                    this[this.tableCustomers.ContactTitleColumn] = value;

                }

            }

            //……..

            //以及其他可以为空字段的对应属性

           

            public bool IsContactNameNull() {

                return this.IsNull(this.tableCustomers.ContactNameColumn);

            }

           

            public void SetContactNameNull() {

                this[this.tableCustomers.ContactNameColumn] = System.Convert.DBNull;

            }

           

            public bool IsContactTitleNull() {

                return this.IsNull(this.tableCustomers.ContactTitleColumn);

            }

           

            public void SetContactTitleNull() {

                this[this.tableCustomers.ContactTitleColumn] = System.Convert.DBNull;

            }

            //……..

 

            //以及其他可以为空字段的IsXXXNull(),SetXXXNull()方法

        }

可见,CustomersRow类添加了不少属性(对应于各个字段),还提供了判断是否为DBNull以及设置DBNull的操作。并且,对这些属性的所有操作其实都是转化为对DataTable相应column对象的操作。

4MyCustomers中定义了类CustomersRowChangeEvent继承自EventArgs

        public class CustomersRowChangeEvent : EventArgs {

            private CustomersRow eventRow;

            private DataRowAction eventAction;

            public CustomersRowChangeEvent(CustomersRow row, DataRowAction action) {

                this.eventRow = row;

                this.eventAction = action;

            }

            public CustomersRow Row {

                get {

                    return this.eventRow;

                }

            }

            public DataRowAction Action {

                get {

                    return this.eventAction;

                }

            }

        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值