DataSet 中的 Relations 属性

示例来自 MSDN,将四个表关联在一起,适应于在操作多表时,有时需要关联表有时不需要关联的情况下(见 CommunityServer 的 cs_shared_Threads_GetThreadSet 存储过程也属此类应用)。

using System;
using System.Data;
using System.Data.SqlClient;

namespace TestDataRelation
{

    class Program
    {
        static void Main()
        {
            PrintOrders("server=(local); uid=sa; pwd=; database=Test_DataSet_DataRelation");
        }

        private static void PrintOrders(string connectionString)
        {
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                DataSet customerOrders = new DataSet();

                connection.Open();

                SqlDataAdapter reader;

                reader = new SqlDataAdapter("SELECT * FROM Customers", connection);
                reader.Fill(customerOrders, "Customers");

                reader = new SqlDataAdapter("SELECT * FROM Orders", connection);
                reader.Fill(customerOrders, "Orders");

                reader = new SqlDataAdapter("SELECT * FROM OrderDetails", connection);
                reader.Fill(customerOrders, "OrderDetails");

                reader = new SqlDataAdapter("SELECT * FROM Products", connection);
                reader.Fill(customerOrders, "Products");

                connection.Close();

                DataRelation customerOrdersRelation = customerOrders.Relations.Add("CustOrders", customerOrders.Tables["Customers"].Columns["CustomerID"], customerOrders.Tables["Orders"].Columns["CustomerID"]);
                DataRelation orderDetailRelation = customerOrders.Relations.Add("OrderDetail", customerOrders.Tables["Orders"].Columns["OrderID"], customerOrders.Tables["OrderDetails"].Columns["OrderID"], false);
                DataRelation orderProductRelation = customerOrders.Relations.Add("OrderProducts", customerOrders.Tables["Products"].Columns["ProductID"], customerOrders.Tables["OrderDetails"].Columns["ProductID"]);

                // 打印所有订单及订单详情
                foreach (DataRow custRow in customerOrders.Tables["Customers"].Rows)
                {
                    Console.WriteLine("客户 ID: " + custRow["CustomerID"] + "\t客户姓名: " + custRow["CustomerName"]);
                    Console.WriteLine("----------------------------------------");

                    foreach (DataRow orderRow in custRow.GetChildRows(customerOrdersRelation))
                    {
                        Console.WriteLine("  订单号: " + orderRow["OrderID"]);
                        Console.WriteLine("\t订单日期: " + orderRow["OrderDate"]);

                        foreach (DataRow detailRow in orderRow.GetChildRows(orderDetailRelation))
                        {
                            Console.WriteLine("\t Product: " + detailRow.GetParentRow(orderProductRelation)["ProductName"]);
                            Console.WriteLine("\t Quantity: " + detailRow["Quantity"]);
                        }

                        Console.WriteLine();
                    }
                }

            }
        }
    }

}

MSDN:

请注意,当为 Customers 表和 Orders 表创建 DataRelation 时,没有为 createConstraints 标志指定任何值(默认为 true)。它假定 Orders 表中的所有行都具有一个存在于父 Customers 表中的 CustomerID 值。如果 CustomerID 存在于 Customers 表之外的 Orders 表中,则 ForeignKeyConstraint 将引发异常。

如果子列可能包含父列不包含的值,添加 DataRelation 时请将 createConstraints 标志设置为 false。在该示例中,对于 Orders 表和 OrderDetails 表之间的 DataRelation,createConstraints 标志将设置为 false。这样,应用程序就可以返回 OrderDetails 表中的所有记录并只返回 Orders 表中记录的子集,而不会生成运行时异常。

float:left 和 margin-left

在 IE6,float:left 和 margin-left一起使用时有 BUG,如:

<div>
    <div style="float:left; margin-left:5px" id="d1">左边有 10 px,而不是 5 px</div>
    <div style="float:left">紧跟 d1</div>
</div>

IE 7 和 Firefox 没有此问题。

CommunityServer 2.1 的 CSCopy 类

  此类支持序列化,此类的主要动作是根据子类的默认构造函数创建一个子类实例,objects 字段是 Hashtable 类型,存放一个键值对,它的键的类型是 Type 类型,值类型是 ConstructorInfo 类型,也就是它存放的是代表子类的构造函数的类型,作用是利用此构造函数类实例 Invoke 出子类的一个实例。

  CSCopy 类还有一个虚拟的成员函数 Copy(),一般地,子类继承时重写此类,然后在子类的 Copy() 函数里调用基类的 CreateNewInstance() 函数(或用 base.Copy())创建对象后,将子类中各成员变量的值赋给新创建的实例。如:

    public override object Copy()
    {
        Thread thread = base.Copy() as Thread;  // 调用 Thread 类的默认构造函数创建的实例

        // 以下的赋值是将当前对象(看到都用 this 了吧)的各成员变量的值赋给新对象,
        // 也就等于 Copy 一个副本,呵呵,从类名都可以看出来
        thread.MostRecentPostAuthor = this.MostRecentPostAuthor;
        thread.MostRecentPostAuthorID = this.MostRecentPostAuthorID;
        thread.AuthorID = this.AuthorID;
        thread.Status = this.Status;
        thread.IsSticky = this.IsSticky;
        thread.StickyDate = this.StickyDate;
        thread.MostRecentPostID = this.MostRecentPostID;

        return thread;
    }

    继承此类的子类一般是需要将对象 Copy 一份,然后另作它用。如:

    public virtual String RenderedBody(PostTarget target)
    {
        Post p = this.Copy() as Post;

        if (p.Section != null)
            CSEvents.PreRenderPost(p,p.Section.ApplicationType,target);
        else
            CSEvents.PreRenderPost(p,ApplicationType.Unknown,target);

        return p.FormattedBody;
    }

PCVCBlog 加了分页功能

  利用元旦两天的假期研究了一下 CommunityServer 2.1 SP1 的几个分页功能,为 PCVCBlog 加上了分页功能,PCVCBlog 提供了两个分页控件,一个是简单型的,一个是多功能型的,多功能的型的跟 baidu.com 和 google.com 的分页一样。同时数据库读取方面也是利用了 SQL Server 2005 的一个新功能:ROW_NUMBER() 函数。分页浏览时是按需读取,也就是根据 PageSize 大小从数据库读取指定条数的记录。在前台只需要指定一下 PageSize 的大小即可:

<Blog:AggregateBlogList runat="server" PageSize="5" />

最后一天假期,下雨了

  好不容易可以整天休息,无奈天空不作美,下起了雨,郁闷!

  凡事都往好的方面想就会好过点,下雨了,我又可以研究 .net 了,又可以学到东西了,也不错嘛,要是下午雨停了,就出去走走,也不能老面对电脑,一天面对9-10小时还不够啊,一年365天,可能有360天是这样度过的,这样做人真没意思,做程序员真没意思……可现在还由不得你做主,不经过风雨怎么能见彩虹!

  外面还是细雨濛濛,漱口洗脸先……

对 ASP.NET 控件的一点理解(整理)

Web 服务器控件和 Html 服务器控件


  一般地,在用 ASP.NET 开发 Web 应用程序时,时时刻刻都与控件打交道,可以说是无处不在,其实 Web 窗体页(.aspx 页)也是控件。

  ASP.NET 控件分为 Web 服务器控件(简称 Web 控件)和 Html 服务器控件(简称 Html 控件),都是运行在服务器端。两者有什么区别呢?

  我们平时用的 HTML 标记,如 <a>、<input> 等,是无法用程序来控制它们的,需用其它如 JavaScript 等程序语言才能得以控制。在 ASP.NET 程序里,我们可以在 HTML 标记加上 runat="server",就可以将相应的 HTML 标记变成 HTML 服务器控件,从而可以以编程的方式来控制这些 HTML 标记。引用(http://www.dvbbs.net/tech/net/2006051268338.asp):


  至于 Html 标注和 Html 控件之间的区别很明显,Html 控件是运行于服务器端,Html 标注是运行于客户端。具体来说:当 ASP.NET 网页执行时,会检查标注有无 runat 属性,如果标注没有设定,那么 Html 标注就会被视为字符串,并被送到字符串流等待送到客户端,客户端的浏览器会对其进行解释;如果 Html 标注有设定 runat="server" 属性,Page 对象会将该控件放入控制器,服务器端的代码就能对其进行控制,等到控制执行完毕后再将 Html 控件的执行结果转换成 Html 标注,然后当成字符串流发送到客户端进行解释。

  对于 Web 服务器控件,是 Web 窗体页中用来定义 Web 应用程序用户界面的组件,是 Web Forms 编程模型的基本元素,尽管 Web 服务器控件呈现为 HTML,但它们的对象模型不一定反映 HTML 语法。

  1、Asp.net 服务器控件提供更加统一的编程接口,如每个 Asp.net 服务器控件都有 Text 属性。

  2、隐藏客户端的不同,这样程序员可以把更多的精力放在业务上,而不用去考虑客户端的浏览器是 ie 还是 firefox,或者是移动设备。

  3、Asp.net 服务器控件可以保存状态到 ViewState 里,这样页面在从客户端回传到服务器端或者从服务器端下载到客户端的过程中都可以保存。

  4、事件处理模型不同,Html 标注和 Html 控件的事件处理都是在客户端的页面上,而 Asp.net 服务器控件则是在服务器上。


创建自定义服务器控件


  一、简述:


  创建用户控件或服务器控件一般是继承于 System.Web.UI.Control 类或 System.Web.UI.WebControls.WebControl 类。如 Web 用户控件(.ascx 页)继承于 System.Web.UI.UserControl 类,后者继承于 System.Web.UI.TemplateContorl 类,后者又继承于 System.Web.UI.Control 类,而 Web 窗体页(.aspx 页)也继承于 System.Web.UI.TemplateContorl 类,为什么中间要多出这些类呢?这些中间类都主要是提供一些共享的属性、方法和事件,总不能把所有的功能都放在 Control 类吧。TemplateContorl 类为 Page 类和 UserControl 类提供一组基本功能。而 Control 类为所有 ASP.NET 服务器控件提供共享的属性、方法和事件,它作为开发自定义 ASP.NET 服务器控件时的派生源的主要类(为什么要说“的主要类”是因为开发这些控件时往往还要实现其它接口以完成更多功能)。咱们平时用得最多的 TextBox 控件则是继承于 System.Web.UI.WebControls.WebControl 类。后者同样也是继承于 System.Web.UI.Control 类。

  Control 没有任何针对用户界面 (UI) 的功能。如果要创建没有 UI 的控件或者组合其他呈现它们自己的 UI 的控件,则从 Control 派生。如果要创建具有 UI 的控件,则从 WebControl 或 System.Web.UI.WebControls 命名空间中的任何控件派生,该命名空间为自定义控件提供适当的起点。

  System.Web.UI.WebControls 命名空间包含一些呈现为 HTML 标记的类,如 TextBox 控件和 ListBox 控件。该命名空间还包含一些不在网页上呈现、但支持数据操作的类,如 SqlDataSource 类和 ObjectDataSource 类。其他一些控件(如 GridView 控件和 DetailsView 控件)支持数据显示和编辑。WebControl 类用作 System.Web.UI.WebControls 命名空间中许多类的基类。


  二、例子:

  1. 一个 MSDN 的例子,创建一个从 Control 类继承且无 UI 功能的控件:


    // MyControl.cs
    using System;
    using System.Web.UI;

    namespace DemoControl
    {
        public class MyControl : System.Web.UI.Control
        {
            protected override void Render(HtmlTextWriter writer)
            {
                if (HasControls() && (Controls[0] is LiteralControl))
                {
                    writer.Write("<H2>Your Message : ");
                    Controls[0].RenderControl(writer);
                    writer.Write("</H2>");
                }
            }
        }
    }

    然后在 aspx 页注册该控件并使用:

    // Test.aspx
    <%@ Page Language="C#" %>
    <%@ Register TagPrefix="UC" Namespace="DemoControl" Assembly="Demo" %>

    <UC:MyControl runat="server">
        <asp:Literal runat="server" Text="http://pcvc.net" />
    </UC:MyControl>

    运行结果:

    <H2>Your Message : </H2>
    http://pcvc.net


  2. 还是 MSDN 的例子:


    namespace SpanControl
    {
        using System;
        using System.Web.UI;
        using System.Web.UI.WebControls;
   
        // Renders the following HTML:
        // <span onclick="alert('Hello');" style="color:Red;">Custom Contents</span>
   
        public class MyWebControl : WebControl
        {
            public MyWebControl() : base(HtmlTextWriterTag.Span)
            { }

            [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
            protected override void AddAttributesToRender(HtmlTextWriter writer)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "alert('Hello');");
                writer.AddStyleAttribute(HtmlTextWriterStyle.Color, "Red");
                writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, "Pointer");
                base.AddAttributesToRender(writer);
            }

            [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
            protected override void RenderContents(HtmlTextWriter writer)
            {
                writer.Write("Custom Contents");
                base.RenderContents(writer);
            }
        }
    }

    在 aspx 页注册该控件并使用:

    // spancontrol.aspx
    <%@ Page Language="C#" %>
    <%@ Register TagPrefix="UC" Namespace="SpanControl" Assembly="Demo" %>

    <UC:MyWebControl runat="server" />

    运行结果:

    <span onclick="alert('Hello');" style="color:Red;cursor:Pointer;">Custom Contents</span>

新一年又开始了

今天是元旦,我还得值班,明后天休息,也没什么安排。

回想 2006 年好像也没做什么,一片空白,唯一一件喜事就是结婚,然后去泰国。公司方面仍然如旧,没什么新的发展,公司网站除了改版还是改版,也赶了一下 web 2.0 的潮流,什么博客、群等,这是好现象,说明思想还是在进步的。

2007 年有什么打算?……

还是拭目以待吧……

使用 Forms 身份验证的一点点心得

如果采用 Forms 验证,当用户通过验证后 Context.User.Identity 或 Page.User.Identity 是一个 System.Security.Principal.IIdentity


System.Security.Principal 命名空间定义表示代码在其中运行的安全上下文的用户对象。

未验证:

Context.User: System.Security.Principal.GenericPrincipal,实现 System.Security.Principal.IPrincipal 接口,表示一般用户
Context.User.Identity: System.Security.Principal.GenericIdentity,实现 System.Security.Principal.IIdentity 接口,表示一般用户

Forms 验证后:

Context.User: 同与未验证
Context.User.Identity: System.Web.Security.FormsIdentity,实现 System.Security.Principal.IIdentity 接口,表示一个使用 Forms 身份验证进行了身份验证的用户标识。


可以根据需要创建自己的用户对象(Principal),需要实现 System.Security.Principal.IPrincipal 接口。


验证后,可以用 FormsAuthentication.SetAuthCookie("UserName", true); 给以 UserName 为用户创建一个票据,事实上是创建一个 Cookies,创建之后,用户在访问那些需要通过用户验证才能访问的页时就不用每次提供票据了(也就是不用每次都输入用户名和密码去登录)。此 Cookies 的过期时间在 web.config 里设置如:

    <authentication mode="Forms">
      <forms name="GLUserAuth" loginUrl="Login.aspx" timeout="10" />
    </authentication>

如以上设置,若用户在 10 分钟内未对应用程序进行任何操作,此票据(cookies)将自动失效。

怎样设置哪些页需要用户通过身份验证后才能访问,用 <location> 配置节:

  <location path="EditUser.aspx">
    <system.web>
      <authorization>
        <deny users="?" />
      </authorization>
    </system.web>
  </location>

当然啦,如果所有页都需要就不是这样设置的了。最后可以用:FormsAuthentication.SignOut() 方法从浏览器删除 Forms 身份验证票证。

Asp.net 中 Password 型 TextBox 在服务器赋值[转]

出于安全性考虑,Asp.net 中 Password 型 TextBox 不允许从服务器赋值;

解决方法:this.txtPassword.Attributes.Add("value",Request.Cookies["pwd"].Value);

地震了,吓了一跳!

  昨晚 20:26 和 20:34 分别发生了两次地震,震中位于台湾南部海域,汕头有震感,部分地区震感稍强,我那可能就属于“稍强”地区吧,我家住七楼,能不强吗?当时我正在书房专心研究 .Net,突然书架的玻璃前后摇动,响得很,还以为是自己身体抖动所致,站起来一看,还在摇,这时突然听见我老婆喊了一声:“哎,地震了!”,我马上跑过去,立式的空调还在动,两人走到阳台,第一次地震已过了。过了一会,老婆打个电话给老妈报个平安,我继续回书房,刚坐下不久,又来了,马上跑了出来,见老婆还在打电话,我说:“快点出去好了”,她挂电话后还拿钥匙,然后跟我说往天台跑,门还是她锁的。此事可见老婆比我还镇定,我两次跑都跑在她前面,唉!愧为男子汉啊!
页次:9/11   每页 10 条   共 107 条   9 1 2 3 4 5 6 7 8 9 10 :