WinForm,MVC知识点

WinForm的一对基础知识,用来回看自身忘记的,唤醒本人的知识。

引言

反射是.Net提需要大家的一件强力武器,固然超越八分之四情状下大家不常用到反射,固然大家大概也不须求掌握它,但对反射的采纳作以开端询问在此后的支付中只怕聚会场全部支持。

反射是1个极大的话题,牵扯到的知识点也很多,包蕴程序集、自定义性情、泛型等,想要完全明白它不行不利。本文仅仅对反射做一个疏忽介绍,关于它更高深的始末,供给在实践中逐步控制。本文将分成上面多少个部分介绍.Net中的反射:

  1. 序章,笔者将因此七个例子来引出反射,获得对反射的第3影象。
  2. 反射开首、Type类、反射普通档次。(修改中,近来宣布…)
  3. 反射特性(Attribute)。
  4. xxxx (待定)

固然未来有MVC可是自家以为依旧要读书一下WinForm的,终归此前也被我们用了过多年。

序章

假诺您还未曾接触过反射,而自个儿以往就下一堆定义告诉您哪些是反光,相信您势必会有2只一棒的觉得。我一向认为那个公理式的概念和定义唯有在你丰富精晓的时候才能较好的发挥功用。所以,我们先来看2个支付中常蒙受的题材,再看看哪些运用反射来化解:

在展开数据库设计的长河中,常常会建立部分基础消息表,比如说:全国的都会,又只怕订单的状态。假如大家将城市的表,起名为City,它通常包括类似那样的字段:

Id     Int Identity(1,1) 城市Id
Name   Varchar(50)           城市名称
ZIP    Varchar(10)           城市邮政编码
… // 略

以此表将供广大别样表引用。即使我们在建立多少个酒吧预约系统,那么饭馆新闻表(Hotel)就会引用此表,用CityId字段来引用饭馆所在城市。对于都市(City)表那种气象,表里存放的记录(城市音讯)是不定的,意思就是说:大家可能天天会向那张表里添加新的都会(当有个别城市的首先家酒馆想要加入预约系统时,就需求在City表里新添这家酒吧所在的城池)。此时,这样的设计是在理的。

基本功知识01

1.建表及其难点

咱俩再看看别的一种状态,大家须求标识酒馆预约的情况:未提交、已交付、已裁撤、受理中、已退回、已订妥、已过期。此时,很多开发职员会在数据库中确立一张小表,叫做BookingStatus(预定情形),然后将如上景况进入进去,就象是那样:

图片 1

有如城市(City)表一样,在系统的其他表,比如说饭馆订单表(HotelOrder)中,通过字段StatusId引用那么些表来获取酒馆预约境况。但是,多少个月之后,纵然看上去和都市表的用法一样,结果却发现那么些表只在数据库做一道查询大概只在先后中调用,却从未做修改,因为预定流程规定下来后一般是不会改变的。在应用程序中,也不会给用户提供对那一个表记录的增加和删除改操作界面。

而在程序中调用这些表时,平时是那种景观:我们须求基于预定情形对订单列表举行筛选。此时不乏先例的做法是使用一个下拉菜单(DropDownList),菜单的数据源(DataSource),大家得以很轻易地因而2个SqlDataReader得到,大家将DropDownList的文本Text设为Status字段,将值Value设为Id字段。

那会儿,我们应该早就意识难点:

  1. 假如大家还有航班预约、游船预约,恐怕别的一些处境,大家需求在数据库中开创很多好像的小表,造成数据库表的数据过多。
  2. 咱俩使用DropDownList等控件获取表内容时,需求接二连三到数据库进行询问,潜在地影响属性。

再正是,大家也注意到三点:

  1. 此表一般会在数据库联合查询中央银行使到。假诺大家有表示商旅订单的HotelOrder表,它包罗代表情形的StatusId字段,大家的询问可能会像这么:Select
    *, (Select Status From BookingStatus Where Id =
    HotelOrder.StatusId) as Status From HotelOrder。
  2. 在应用程序中,此表平常作为DropDownList或然别的List控件的数据源。
  3. 本条表大致平昔不改动。

1:贰个控件有好多的风浪,每一种事件都有广大的政工要做,首借使透过_click的事件来决定的。

2.数组及其难点

意识到那样设计存在难题,大家未来就想办法缓解它。大家所想到的第7个点子是能够在程序中开创1个数组来代表预定情状,那样我们就能够删掉BookingStatus状态表(注意可以如此做是因为BookingStatus表的内容明确后大致向来不改动)。

string[] BookingStatus = {  
   “NoUse”,
“未提交”,”已提交”,”已取消”,”受理中”,”已退回”,”已订妥”,”已过期”
};     //
注意数组的0号成分仅仅是起2个占位效用,以使程序简洁。因为StatusId从1从头。

作者们先看它化解了哪些:上边提到的题目一 、难点2都消除了,既不须要在数据库中创设表,又无需三番五次到数据库进行查询。

咱俩再看看当大家想要用文件展现酒馆的订购时,该怎么办(若是有订单类HotelOrder,其属性StatusId代表订单状态,为int类型
)。

// GetItem用于获取3个饭馆订单对象, orderId为int类型,代表订单的Id
HotelOrder myOrder = GetItem(orderId);
lbStatus.Text = BookingStatus[myOrder.StatusId]; 
//lbStatus是一个Label控件

近年来截至看上去还不易,今后大家须求进行一个操作,将订单的图景改为“受理中”。

myOrder.StatusId = 4;

很不幸,大家发现了接纳数组恐怕带来的首先个难点:不方便使用,当我们需求更新订单的场馆值时,大家须求去查看BookingStatus数组的定义(除非你记住全体情形的数字值),然后根据事态值在数组中的地点来给目的的习性赋值。

我们再看另2个操作,要是某些订单的情事为“已过期”,就要对它实行删除:

if(BookingStatus[myOrder.StatusId]==”已过期”){
    DeleteItem(myOrder);     // 删除订单
}

那时的题材和上边的类似:大家必要手动输入字符串“已过期”,此时Vs二〇〇六的智能提示发挥不了任何效果,假使大家不幸将状态值记错,只怕手误打错,就将促成程序不当,较为妥善的做法还是按下F12导向到BookingStatus数组的定义,然后将“已过期”复制过来。

今昔,大家再看看哪些来绑定到一个DropDownList下拉列表控件(Id为ddlStatus)上。

ddlStatus.DataSource = BookingStatus;
ddlStatus.DataBind();

只是大家发现发生的HTML代码是如此:

<select name=”ddlStatus” id=”ddlStatus”>
    <option value=”未提交”>未提交</option>
    <option value=”已提交”>已提交</option>
    <option value=”已取消”>已取消</option>
    <option value=”受理中”>受理中</option>
    <option value=”已退回”>已退回</option>
    <option value=”已订妥”>已订妥</option>
    <option value=”已过期”>已过期</option>
</select>

大家来看,列表项的value值与text值相同,那肯定不是我们想要的,如何做吧?我们得以给下拉列表写3个多少绑定的事件处理方法。

protected void Page_Load(object sender, EventArgs e) {   
    ddlStatus.DataSource = BookingStatus;
    ddlStatus.DataBound += new EventHandler(ddlStatus_DataBound);
    ddlStatus.DataBind();
}

void ddlStatus_DataBound(object sender, EventArgs e) {
    int i = 0;
    ListControl list = (ListControl)sender;
//注意,将sender转换成ListControl
    foreach (ListItem item in list.Items) {
       i++;
       item.Value = i.ToString();         
    }
}

如此那般,大家运用数组达成了咱们愿意的作用,尽管如此实现显得有个别困苦,尽管还存在上边提到的不便利使用的题材,但那几个标题大家耐心细致一点就能克服,而软件开发大约一直就从不百分百到家的化解方案,那我们大约就这么好了。

NOTE:在ddlStatus_DataBound事件中,引发事件的对象sender分明是DropDownList,不过此地却不曾将sender转换到DropDownList,而是将它转换来基类型ListControl。那样做是为了更好地拓展代码重用,ddlStatus_DataBound事件处理方法将不仅限于
DropDownList,对于接二连三自ListControl的任何控件,比如RadioButtonList、ListBox也足以不加改动地利用ddlStatus_DataBound方法。

    假诺您对事件绑定还面生,请参考
C#中的委托和事件
一文。

    这里也能够采取Dictionary<String,
Int>来成功,但都设有类似的难题,就不再举例了。

点击按钮调用TextBox的Hide方法,调用控件的章程序控制件就会发出动作。而此情势是使那些小窗口没有隐藏。

3.枚举及其难题

可是不幸的事又产生了…
大家的预购程序分成两有的:一部分为B/S端,在B/S端能够展开客栈订单的
成立(未提交)、提交(已提交)、废除提交(已打消),此外还足以看来是或不是已订妥;一部分为C/S端,为饭馆的预购基本,它能够拓展任何意况的操作。

那时,对于整个系统来说,应该有百分之百的多少个情景。但对于B/S端来说,它只有未提交、已交付、已吊销、已订妥 八个状态,相应的值分别为 ① 、② 、叁 、6。

大家回看一下方面是哪些行使数组来消除的,它存在三个缺点:咱俩默许地将订单状态值与数组的索引一一对应地联系了起来。

从而在绑定DropDownList时,大家选取自增的章程来设定列表项的Value值;大概在显示状态时,我们由此lbStatus.Text
= BookingStatus[myOrder.StatusId];
那样的语句来达成。而当那种对应关系被打破时,使用数组的点子就失效了,因为一旦不利用数组索引,大家尚无额外的地方去存款和储蓄状态的数字值。

那时候,我们想到了应用枚举:

public enum BookingStatus {
    未提交 = 1,
    已提交,
    已取消,
    已订妥 = 6
}

笔者们想在页面输出3个订单的境况时,能够如此:

HotelOrder myOrder = GetItem(orderId);         //获取三个订单对象
lbStatus.Text = ((BookingStatus)myOrder.StatusId).ToString(); //
输出文本值

大家想翻新订单的景况为 “已交付”:

myOrder.StatusId = (int)BookingStatus.已提交;

当状态为“已撤销”时大家想进行某个操作:

if(BookingStatus.已取消 == (BookingStatus)myOrder.StatusId){
    // Do some action
}

那儿,VS 2007的智能提醒已经足以发挥完全意义,当大家在BookingStatus后按下“.”时,可以来得出装有的气象值。

NOTE:当大家采纳枚举存款和储蓄状态时,myOrder对象的StatusId最好为BookingStatus枚举类型,而非int类型,那样操作会特别方便人民群众一些,但为了和前面使用数组时的情形保持统一,那里StatusId仍利用int类型。

以上三种境况选取枚举都来得11分的绕梁之音,直到我们要求绑定枚举到DropDownList下拉列表的时候:我们精晓,能够绑定到下拉列表的有两类对象,一类是完成了IEnumerable接口的可枚举集合,比如ArrayList,String[],List<T>;一类是完结了IListSource的数据源,比如DataTable,DataSet。

NOTE:实际上IListSource接口的GetList()方法重返一个IList接口,IList接口又延续了IEnumerable接口。由此看来,IEnumerable是贯彻可枚举集合的基础,在自个儿翻译的一篇小说
C#中的枚举器
中,对这些核心做了详实的座谈。

可大家都理解:枚举enum是三个基本类型,它不会兑现任何的接口,那么大家下去该咋做吧?

2:将String类型的变换为int类型

4.施用反射遍历枚举字段

最笨也是最简单易行的艺术,大家得以先创制3个GetDataTable方法,此方法根据枚举的字段值和数字值营造二个DataTable,最终回来那些营造好的DataTable:

  private static DataTable GetDataTable() {
     DataTable table = new DataTable();
     table.Columns.Add(“Name”, Type.GetType(“System.String”));      
//创建列
     table.Columns.Add(“Value”, Type.GetType(“System.Int32”));      
//创建列

     DataRow row = table.NewRow();
     row[0] = BookingStatus.未提交.ToString();
     row[1] = 1;
     table.Rows.Add(row);

     row = table.NewRow();
     row[0] = BookingStatus.已提交.ToString();
     row[1] = 2;
     table.Rows.Add(row);

     row = table.NewRow();
     row[0] = BookingStatus.已取消.ToString();
     row[1] = 3;
     table.Rows.Add(row);

     row = table.NewRow();
     row[0] = BookingStatus.已订妥.ToString();
     row[1] = 6;
     table.Rows.Add(row);

     return table;
 }

接下去,为了方便使用,大家再成立一个特地采纳那么些DataTable来安装列表控件的章程SetListCountrol():

// 设置列表
 public static void SetListControl(ListControl list) {
     list.DataSource = GetDataTable();      // 获取DataTable
     list.DataTextField = “Name”;
     list.DataValueField = “Value”;
     list.DataBind();
 }

近年来,大家就能够在页面中如此去将枚举绑定到列表控件:

protected void Page_Load(object sender, EventArgs e)
{
    SetListControl(ddlStatus);   // 要是页面中已有ID为ddlStatus
的DropDownList
}

比方持有的枚举都要因此那样去绑定到列表,作者认为还不如在数据库中平素建表,那样实在是太难为了,而且我们是基于枚举的公文和值去HardCoding出多个DataTable的:

DataRow row = table.NewRow();
row[0] = BookingStatus.未提交.ToString();
row[1] = 1;
table.Rows.Add(row);

row = table.NewRow();
row[0] = BookingStatus.已提交.ToString();
row[1] = 2;
table.Rows.Add(row);

row = table.NewRow();
row[0] = BookingStatus.已取消.ToString();
row[1] = 3;
table.Rows.Add(row);

row = table.NewRow();
row[0] = BookingStatus.已订妥.ToString();
row[1] = 6;
table.Rows.Add(row);

本条时候,大家想有没有法子通过遍历来达成那里?假如想要遍历那里,首先,大家须求一个带有枚举的各类字段音信的靶子,那么些指标至少含有两条新闻,2个是字段的公文(比如“未提交”),三个是字段的数字型值(比如1),我们权且管那几个指标叫做field。其次,应该存在3个可遍历的、包涵了字段音讯的靶子(也便是filed)
的成团,大家临时管这么些集合叫做enum菲尔德s。

那正是说,上边就足以如此去落到实处:

foreach (xxxx field in enumFields)
{
    DataRow row = table.NewRow();
    row[0] = 田野(field).Name;         // 杜撰的属性,代表
文本值(比如“未提交”)
    row[1] = filed.intValue;     // 杜撰的天性,代表 数字值(比如1)

    table.Rows.Add(row);
}

那段代码很不完整,我们注意到
xxxx,它应当是包装了字段信息(可能叫元数据metadata)的靶子的项目。而对此enumFields,它的品种应该是xxxx那个类型的成团。那段代码是大家遵照思路假想和演绎出来的。实际上,.Net
中提供了 Type类 和 System.Reflection命名空间来支持缓解大家后天的标题。

本身在后头将较详细地介绍
Type类,今后只盼望您能对反射有个第二影象,所以只简单地作以表达:Type抽象类提供了拜访类型元数据的力量,当你实例化了多少个Type对象后,你能够经过它的习性和措施,获取项指标元数据新闻,或然进一步获得该品种的积极分子的元数据。小心到此处,因为Type对象总是基于某一门类的,并且它是二个抽象类,故而大家在成立Type类型时,必供给提供
类型,可能项目标实例,或然项指标字符串值(Part.2会表达)。

创造Type对象有很二种措施,本例中,大家运用typeof操作符来进行,并传递BookingStatus枚举:

Type enumType = typeof(BookingStatus);

接下来,大家理应想艺术获得 封装了字段信息的目的 的集纳。Type类提供
GetFields()方法来落成这一经过,它回到1个 FieldInfo[]
数组。实际上,也正是上面大家enum菲尔德s集合的品种。

FieldInfo[] enumFields = enumType.GetFields();

以后,我们就足以遍历这一会面:

foreach (FieldInfo field in enumFields)
{
    if (!field.IsSpecialName)
    {
       DataRow row = table.NewRow();
       row[0] = 田野(field).Name;     // 获取字段文本值
       row[1] = Convert.ToInt32(myField.GetRawConstantValue()); //
获取int数值
       table.Rows.Add(row);
    }
}

此处田野的Name属性获取了枚举的文本,GetRawConstantValue()方法得到了它的int类型的值。

咱俩看一看完整的代码:

private static DataTable GetDataTable() {

     Type enumType = typeof(BookingStatus);    // 创造项目
     FieldInfo[] enumFields = enumType.GetFields();   
//获取字段信息目的集合

     DataTable table = new DataTable();
     table.Columns.Add(“Name”, Type.GetType(“System.String”));
     table.Columns.Add(“Value”, Type.GetType(“System.Int32”));
    // 遍历集合
     foreach (FieldInfo field in enumFields) {
        if (!field.IsSpecialName) {
            DataRow row = table.NewRow();
            row[0] = field.Name;
            row[1] = Convert.ToInt32(field.GetRawConstantValue());
            //row[1] = (int)Enum.Parse(enumType, 田野(field).Name);
//也得以这么

            table.Rows.Add(row);
        }
     }

     return table;
 }

注意,SetListControl()方法照旧留存并实用,只是为着省去篇幅,作者从未复制过来,它的施用和事先是一律的,我们只是修改了GetDataTable()方法。

                  
string a;     

5.使用泛型来完毕代码重用

观测地点的代码,借使大家今后有另一个枚举,叫做TicketStatus,那么大家要将它绑定到列表,大家唯一须求变更的便是此处:

Type enumType = typeof(BookingStatus); //将BookingStatus改作TicketStatus

既是那样,我们何不定义一个泛型类来拓展代码重用呢?大家管这一个泛型类叫做EnumManager<TEnum>。

public static class EnumManager<TEnum>
{
    private static DataTable GetDataTable()
    {
       Type enumType = typeof(TEnum);  // 获取项目对象
       FieldInfo[] enumFields = enumType.GetFields();

       DataTable table = new DataTable();
       table.Columns.Add(“Name”, Type.GetType(“System.String”));
       table.Columns.Add(“Value”, Type.GetType(“System.Int32”));
       //遍历集合
       foreach (FieldInfo field in enumFields)
       {
           if (!field.IsSpecialName)
           {
               DataRow row = table.NewRow();
              row[0] = field.Name;
              row[1] = Convert.ToInt32(field.GetRawConstantValue());
              //row[1] = (int)Enum.Parse(enumType, 田野先生.Name);
也得以这么

              table.Rows.Add(row);
           }
       }
       return table;
    }

    public static void SetListControl(ListControl list)
    {
       list.DataSource = GetDataTable();
       list.DataTextField = “Name”;
       list.DataValueField = “Value”;
       list.DataBind();
    }
}

OK,未来全部都变得简便的多,现在,大家再需求将枚举绑定到列表,只要这么就行了(ddl开首的是DropDownList,rbl开始的是RadioButtonList):

EnumManager<BookingStauts>.SetListControl(ddlBookingStatus);
EnumManager<TicketStatus>.SetListControl(rblTicketStatus);

NOTE:即便您对泛型面生,请参阅 C#
中的泛型

一文。上边的达成并不曾考虑到质量的标题,仅仅为了引出反射使用的叁个实例。

                   int
b;

6 .Net 中反射的二个范例。

不管是VS贰零零陆的智能提醒,还是修改变量名时的重构功用,都利用了反光成效。在.Net
FCL中,也时不时能看出反射的阴影,那里就向我们演示二个最广泛的事例。我们明白,在CLOdyssey中累计有两种类型,一种是值类型,一种是引用类型。声澳优(Ausnutria Hyproca)个引用类型的变量并对项目实例化,会在应用程序堆(Application
Heap)上分配内部存款和储蓄器,创造对象实例,然后将对象实例的内存地址再次来到给变量,变量保存的是内部存款和储蓄器地址,实际也等于2个指南针;声Bellamy(Bellamy)个值类型的实例变量,则会将它分配在线程堆栈(Thread
Stack)上,变量本人包罗了值类型的具有字段。

今昔若是大家须要比较多少个目的是否等于。当大家比较多少个引用类型的变量是不是等于时,我们相比较的是那多个变量所针对的是否堆上的同二个实例(内部存款和储蓄器地址是还是不是相同)。而当我们相比较三个值类型变量是不是等于时,怎么办吧?因为变量本身就包罗了值类型全部的字段(数据),所以在比较时,就须求对七个变量的字段进行逐一的万分的可比,看看每一个字段的值是或不是都特出,借使别的多个字段的值不等,就回到false。

实际,执行那样的贰个相比并不须要大家和好编辑代码,Microsoft已经为大家提供了贯彻的法子:全部的值类型继承自
System.ValueType, ValueType和具有的档次都一而再自System.Object
,Object提供了3个Equals()方法,用来判断四个目的是还是不是等于。不过ValueType覆盖了Object的Equals()方法。当大家相比较七个值类型变量是还是不是等于时,可以调用继承自ValueType类型的Equals()方法。

public struct ValPoint {
    public int x;
    public int y;
}
static void Main(string[] args) {
    bool result;

    ValPoint A1;
    A1.x = A1.y = 3;

    ValPoint B1 = A1;            // 复制A的值给B
    result = A1.Equals(B1);
    Console.WriteLine(result);      // 输出 True;
}

你有没有想到当调用Equals()方法时会产生什么事呢?前边大家早已涉嫌要是是值类型,会对五个变量的字段举办逐项的可比,看看每一种字段的值是或不是都等于,可是怎么取得变量的具备字段,遍历字段,并逐一相比呢?此时,你应有发现到又到了用到反射的时候了,让大家运用reflector来查阅ValueType类的Equals()方法,看看微软是什么做的啊:

public override bool Equals(object obj) {
    if (obj == null) {
       return false;
    }
    RuntimeType type = (RuntimeType)base.GetType();
    RuntimeType type2 = (RuntimeType)obj.GetType();
    if (type2 != type) {
       return false;
    }
    object a = this;
    if (CanCompareBits(this)) {
       return FastEqualsCheck(a, obj);
    }
    // 获取具有实体字段
    FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Instance);
    // 遍历字段,判断字段值是还是不是等于
    for (int i = 0; i < fields.Length; i++) {
       object obj3 = ((RtFieldInfo)fields[i]).InternalGetValue(a,
false);
       object obj4 = ((RtFieldInfo)fields[i]).InternalGetValue(obj,
false);
       if (obj3 == null) {
           if (obj4 != null) {
              return false;
           }
       } else if (!obj3.Equals(obj4)) {
           return false;
       }
    }
    return true;
}

小心到地点加注释的那两段代码,可以见见当对值变量进行相比时,是会使用反射来完毕。反射存在着品质不好的题材(不仅如此,还留存着累累的装箱操作),可想而知,在值类型上调用Equals()方法开发是会非常的大的。可是这么些例子只是为了验证反射的用处,小编想已经实现了目标。上边的代码不可能一心知晓也没什么,前边会再涉及。

                  
if(int.TryParse(a,out b))

7.小结

观察此间,你应有对反射有了3个发端的概念(大概叫反射的1个用场):反射是一种常见的叫法,它经过
System.Reflection 命名空间 并 配合 System.Type
类,提供了在运作时(Runtime)对于 类型和对象(及其成员)的中坚音信 以及
元数据(metadata)的访问能力。

 

在if语句的括号里面就将string类型转换为int类型的了。

3:return知识退出当前的函数,不是脱离当前的顺序。

4:排错技巧,在阴差阳错的地点设置断点,占星关变量的值。

5:[static]静态成员就算没有类的实例化也设有,也足以被访问到,不用在头里实例化。

6:控件的名要有含义,不可随意起名。局地变量每一趟运营完值都会被销毁,下次再运行,会再一次初叶化,而类的字段只借使1个目的,那么一旦对象不销毁,就一向保持不变。

7:退出程序

    
this.Close();

    
Application.Exit();

MVC基础

1:开源

 
免费开放源代码,要有和好完全的社区,论坛等沟通平台。(促进编制程序人士进行交换)

 
学习人家什么写代码,自个儿的创作风格就会有必然的提高。

2:实体框架(EF)

 
*与Asp.net的联系,Ado.net的联系。。

 
*为指标关系对应消除方案。

 
*是ADO.NET的一组扶助开发面向数据的软件应用程序的技艺是OHighlanderM框架的一种。

3:O/R
Mapping

(O途乐M)是一种表实体与表直接的交互转换。是面向对象的靶子模型和事关行数据库的数据结构之间的相互转换。是依照关系型数据库的多少存款和储蓄,达成二个虚拟的面向对象的多寡访问接口。

4:

*数据库中表的命名规范便是程序中类的命名。

*EF中负有的实业要求求有主键,那样子就不会报错。

EF:是一个ORM框架;
O奇骏M:表实体与表之间的交互转化。
操作数据库的是ADO.NET
EF:必须经过>Ado.net>Sql>Database【正是协助大家把实体的转变翻译为Sql脚本,然后调用Ado.net保存到数据库中的】

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图