[架构]最便宜的高负载网站架构

mikel阅读(871)

  原文链接:http://www.javaeye.com/blog/52178
  说明:可以参看原链接的评论
  ===================================================
  1, LVS做前端四层均衡负载
  基于IP虚拟分发的规则,不同于apache,squid这些7层基于http协议的反向代理软件, LVS在性能上往往能得到更好的保证!
  
  2,squid 做前端反向代理加缓存
  squid 是业内公认的优秀代理服务器,其缓存能力更让许多高负载网站青睐!(比如新浪,网易等)
  使用他, 配合ESI做WEB动态内容及图片缓存,最合适不过了
  
  3,apache 用来处理php或静态html,图片
  apache是业内主流http服务器,稳定性与性能都能得到良好保证!
  
  4,JBOSS 用来处理含复杂的业务逻辑的请求
  JBOSS是red hat旗下的优秀中间件产品,在java开源领域小有名气,并且完全支持j2ee规范的,功能非常强大
  使用他,既能保证业务流程的规范性,又可以节省开支(免费的)
  
  5,mySQL数据库
  使用mySQL数据库,达到百万级别的数据存储,及快速响应,应该是没问题的
  
  6,memcache作为分布式缓存
  缓存应用数据,或通过squid解析esi后,作为数据载体

[教程]Linq to SQL 查询

mikel阅读(716)

原贴
    简单地说,LINQ 是支持以类型安全方式查询数据的一系列语言扩展;它将在代号为“Orcas”的下一个版本 Visual Studio 中发布。待查询数据的形式可以是 XML(LINQ 到 XML)、数据库(启用 LINQ 的 ADO.NET,其中包括 LINQ 到 SQL、LINQ 到 Dataset 和 LINQ 到 Entities)和对象 (LINQ 到 Objects) 等。LINQ 体系结构如图 1 所示。


让我们看一些代码。在即将发布的“Orcas”版 C# 中,LINQ 查询可能如下所示:

var overdrawnQuery = from account in db.Accounts

                     where account.Balance < 0

                     select new { account.Name, account.Address };

当使用 foreach 遍历此查询的结果时,返回的每个元素都将包含一个余额小于 0 的帐户的名称和地址。

从 以上示例中立即可以看出该语法类似于 SQL。几年前,Anders Hejlsberg(C# 的首席设计师)和 Peter Golde 曾考虑扩展 C# 以更好地集成数据查询。Peter 时任 C# 编译器开发主管,当时正在研究扩展 C# 编译器的可能性,特别是支持可验证 SQL 之类特定于域的语言语法的加载项。另一方面,Anders 则在设想更深入、更特定级别的集成。他当时正在构思一组“序列运算符”,能在实现 IEnumerable 的任何集合以及实现 IQueryable 的远程类型查询上运行。最终,序列运算符的构思获得了大多数支持,并且 Anders 于 2004 年初向比尔·盖茨的 Thinkweek 递交了一份关于本构思的文件。反馈对此给予了充分肯定。在设计初期,简单查询的语法如下所示:

sequence<Customer> locals = customers.where(ZipCode == 98112);

在 此例中,Sequence 是 IEnumerable<T> 的别名;“where”一词是编译器能理解的一种特殊运算符。Where 运算符的实现是一种接受 predicate 委托(即 bool Pred<T>(T item) 形式的委托)的普通 C# 静态方法。本构思的目的是让编辑器具备与运算符有关的特殊知识。这样将允许编译器正确调用静态方法并创建代码,将委托与表达式联系起来。

假设上述示例是 C# 的理想查询语法。在没有任何语言扩展的情况下,该查询在 C# 2.0 中又会是什么样子?

IEnumerable<Customer> locals = EnumerableExtensions.Where(customers,

                                                    delegate(Customer c)

        {

            return c.ZipCode == 98112;

        });

这 个代码惊人地冗长,而且更糟糕的是,需要非常仔细地研究才能找到相关的筛选器 (ZipCode == 98112)。这只是一个简单的例子;试想一下,如果使用数个筛选器、投影等,要读懂代码该有多难。冗长的根源在于匿名方法所要求的语法。在理想的查询 中,除了要计算的表达式,表达式不会提出任何要求。随后,编译器将尝试推断上下文;例如,ZipCode 实际上引用了 Customer 上定义的 ZipCode。如何解决这一问题?将特定运算符的知识硬编码到语言中并不能令语言设计团队满意,因此他们开始为匿名方法寻求替代语法。他们要求该语法应 极其简练,但又不必比匿名方法当前所需的编译器要求更多的知识。最终,他们发明了 lambda 表达式。


Lambda
表达式

Lambda 表 达式是一种语言功能,在许多方面类似于匿名方法。事实上,如果 lambda 表达式首先被引入语言,那么就不会有对匿名方法的需要了。这里的基本概念是可以将代码视为数据。在 C# 1.0 中,通常可以将字符串、整数、引用类型等传递给方法,以便方法对那些值进行操作。匿名方法和 lambda 表达式扩展了值的范围,以包含代码块。此概念常见于函数式编程中。

我们再借用以上示例,并用 lambda 表达式替换匿名方法:

IEnumerable<Customer> locals =

    EnumerableExtensions.Where(customers, c => c.ZipCode == 91822);

有 几个需要注意的地方。对于初学者而言, lambda 表达式简明扼要的原因有很多。首先,没有使用委托关键字来引入构造。取而代之的是一个新的运算符 =>,通知编译器这不是正则表达式。其次,Customer 类型是从使用中推断出来的。在此例中,Where 方法的签名如下所示:

public static IEnumerable<T> Where<T>(

    IEnumerable<T> items, Func<T, bool> predicate)

编 译器能够推断“c”是指客户,因为 Where 方法的第一个参数是 IEnumerable<Customer>,因此 T 事实上必须是 Customer。利用这种知识,编译器还可验证 Customer 具有一个 ZipCode 成员。最后,没有指定的返回关键字。在语法形式中,返回成员被省略,但这只是为了语法便利。表达式的结果仍将视为返回值。

与匿名方法一样,Lambda 表达式也支持变量捕获。例如,对于在 lambda 表达式主体内包含 lambda 表达式的方法,可以引用其参数或局部变量:

public IEnumerable<Customer> LocalCusts(

    IEnumerable<Customer> customers, int zipCode)

{

    return EnumerableExtensions.Where(customers,

        c => c.ZipCode == zipCode);

}

最后,Lambda 表达式支持更冗长的语法,允许您显式指定类型,以及执行多条语句。例如:

return EnumerableExtensions.Where(customers,

    (Customer c) => { int zip = zipCode; return c.ZipCode == zip; });

好消息是,我们向原始文章中提议的理想语法迈进了一大步,并且我们能够利用一个通常能在查询运算符以外发挥作用的语言功能来实现这一目标。让我们再次看一下我们目前所处的阶段:

IEnumerable<Customer> locals =

    EnumerableExtensions.Where(customers, c => c.ZipCode == 91822);

这里存在一个明显的问题。客户目前必须了解此 EnumerableExtensions 类,而不是考虑可在 Customer 上执行的操作。另外,在多个运算符的情况下,使用者必须逆转其思维以编写正确的语法。例如:

IEnumerable<string> locals =

    EnumerableExtensions.Select(

        EnumerableExtensions.Where(customers, c => c.ZipCode == 91822),

        c => c.Name);

请注意,Select 属于外部方法,尽管它是在 Where 方法结果的基础上运行的。理想的语法应该更类似以下代码:

sequence<Customer> locals =

    customers.where(ZipCode == 98112).select(Name);

因此,是否可利用另一种语言功能来进一步接近实现理想语法呢?


扩展方法

结 果证明,更好的语法将以被称为扩展方法的语言功能形式出现。扩展方法基本上属于可通过实例语法调用的静态方法。上述查询问题的根源是我们试图向 IEnumerable<T> 添加方法。但如果我们要添加运算符,如 Where、Select 等,则所有现有和未来的实现器都必须实现那些方法。尽管那些实现绝大多数都是相同的。在 C# 中共享“接口实现”的唯一方法是使用静态方法,这是我们处理以前使用的 EnumerableExtensions 类的一个成功方法。

假设我们转而将 Where 方法编写为扩展方法。那么,查询可重新编写为:

IEnumerable<Customer> locals =

    customers.Where(c => c.ZipCode == 91822);

对于此简单查询,该语法近乎完美。但将 Where 方法编写为扩展方法的真正含义是什么呢?其实非常简单。基本上,因为静态方法的签名发生更改,因此“this”修饰符就被添加到第一个参数:

public static IEnumerable<T> Where<T>(

    this IEnumerable<T> items, Func<T, bool> predicate)

此 外,必须在静态类中声明该方法。静态类是一种只能包含静态成员,并在类声明中用静态修饰符表示的类。这就它的全部含义。此声明指示编译器允许在任何实现 IEnumerable<T> 的类型上用与实例方法相同的语法调用 Where。但是,必须能够从当前作用域访问 Where 方法。当包含类型处于作用域内时,方法也在作用域内。因此,可以通过 Using 指令将扩展方法引入作用域。(有关详细信息,请参见侧栏上的“扩展方法”。)

扩展方法

显然,扩展 方法有助于简化我们的查询示例,但除此之外,这些方法是不是一种广泛有用的语言功能呢?事实证明扩展方法有多种用途。其中一个最常见的用途可能是提供共享接口实现。例如,假设您有以下接口:

interface IDog

{

    // Barks for 2 seconds

    void Bark();

    void Bark(int seconds);

}

此接口要求每个实现器都应编写适用于两种重载的实现。有了“Orcas”版 C#,接口变得很简单:

interface IDog

{

    void Bark(int seconds);

}

扩展方法可添加到另一个类:

static class DogExtensions

{

    // Barks for 2 seconds

    public static void Bark(this IDog dog)

    {

        dog.Bark(2);

    }

}

接口实现器现在只需实现单一方法,但接口客户端却可以自由调用任一重载。

我们现在拥有了用于编写筛选子句的非常接近理想的语法,但“Orcas”版 C# 仅限于此吗?并不全然。让我们对示例稍作扩展,相对于整个客户对象,我们只投影出客户名称。如我前面所述,理想的语法应采用如下形式:

sequence<string> locals =

    customers.where(ZipCode == 98112).select(Name);

仅用我们讨论过的语言扩展,即 lambda 表达式和扩展方法,此代码可重新编写为如下所示:

IEnumerable<string> locals =

    customers.Where(c => c.ZipCode == 91822).Select(c => c.Name);

请注意,此查询的返回类型不同,它是 IEnumerable<string> 而不是 IEnumerable<Customer>。这是因为我们仅从 select 语句中返回客户名称。

当投影只是单一字段时,该方法确实很有效。但是,假设我们不仅要返回客户的名称,还要返回客户的地址。理想的语法则应如下所示:

locals = customers.where(ZipCode == 98112).select(Name, Address);


匿名类型

如果我们想继续使用我们现有的语法来返回名称和地址,我们很快便会面临问题,即不存在仅包含 Name 和 Address 的类型。虽然我们仍然可以编写此查询,但是必须引入该类型:

class CustomerTuple

{

    public string Name;

    public string Address;

    public CustomerTuple(string name, string address)

    {

        this.Name = name;

        this.Address = address;

    }

}

然后我们才能使用该类型,即此处的 CustomerTuple,以生成我们查询的结果。

IEnumerable<CustomerTuple> locals =

    customers.Where(c => c.ZipCode == 91822)

                 .Select(c => new CustomerTuple(c.Name, c.Address));

那 确实像许多用于投影出字段子集的样板代码。而且还往往不清楚如何命名此种类型。CustomerTuple 确实是个好名称吗?如果投影出 Name 和 Age 又该如何命名?那也可以叫做 CustomerTuple。因此,问题在于我们拥有样板代码,而且似乎无法为我们创建的类型找到任何恰当的名称。此外,还可能需要许多不同的类型,如何 管理这些类型很快便可能成为一个棘手的问题。

这正是匿名类型要解决的问题。此功能主要允许在无需指定名称的情况下创建结构化类型。如果我们使用匿名类型重新编写上述查询,其代码如下所示:

locals = customers.Where(c => c.ZipCode == 91822)

                       .Select(c => new { c.Name, c.Address });

此代码会隐式创建一个具有 Name 和 Address 字段的类型:

class

{

    public string Name;

    public string Address;

}

此类型不能通过名称引用,因为它没有名称。创建匿名类型时,可显式声明字段的名称。例如,如果正在创建的字段派生于一条复杂的表达式,或纯粹不需要名称,就可以更改名称:

locals = customers.Where(c => c.ZipCode == 91822)

    .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,

                       HomeAddress = c.Address });

在此情形下,生成的类型具有名为 FullName 和 HomeAddress 的字段。

这样我们又向理想世界前进了一步,但仍存在一个问题。您将发现,我在任何使用匿名类型的地方都策略性地省略了局部变量的类型。显然我们不能声明匿名类型的名称,那我们如何使用它们?


隐式类型化部变量

还有另一种语言功能被称为隐式类型化局部变量(或简称为 var),它负责指示编译器推断局部变量的类型。例如:

var integer = 1;

在此例中,整数具有 int 类型。请务必明白,这仍然是强类型。在动态语言中,整数的类型可在以后更改。为说明这一点,以下代码不会成功编译:

var integer = 1;

integer = “hello”;

C# 编译器将报告第二行的错误,表明无法将字符串隐式转换为 int。

在上述查询示例中,我们现在可以编写完整的赋值,如下所示:

var locals =

   customers

       .Where(c => c.ZipCode == 91822)

       .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,

                          HomeAddress = c.Address });

局部变量的类型最终成为 IEnumerable<?>,其中“?”是无法编写的类型的名称(因为它是匿名的)。

隐式类型化局部变量只是:方法内部的局部变量。它们无法超出方法、属性、索引器或其他块的边界,因为该类型无法显式声明,而且“var”对于字段或参数类型而言是非法的。

事实证明,隐式类型化局部变量在查询的环境之外非常便利。例如,它有助于简化复杂的通用实例化:

var customerListLookup = new Dictionary<string, List<Customer>>();

现在我们的查询取得了良好进展;我们已经接近理想的语法,而且我们是用通用语言功能来达成的。

有趣的是,我们发现,随着越来越多的人使用过此语法,经常会出现允许投影超越方法边界的需求。如我们以前所看到的,这是可能的,只要从 Select 内部调用对象的构造函数来构建对象即可。但是,如果没有用来准确接受您需要设置的值的构造函数,会发生什么呢?


对象初始值

为解决这一问题,即将发布的“Orcas”版本提供了一种被称为对象初始值的 C# 语言功能。对象初始值主要允许在单一表达式中为多个属性或字段赋值。例如,创建对象的常见模式是:

Customer customer = new Customer();

customer.Name = “Roger”;

customer.Address = “1 Wilco Way”;

此时,Customer 没有可以接受名称和地址的构造函数;但是存在两个属性,即 Name 和 Address,当创建实例后即可设置它们。对象初始值允许使用以下语法创建相同的结果:

Customer customer = new Customer()

    { Name = “Roger”, Address = “1 Wilco Way” };

在我们前面的 CustomerTuple 示例中,我们通过调用其构造函数创建了 CustomerTuple 类。我们也可以通过对象初始值获得同样的结果:

var locals =

    customers

        .Where(c => c.ZipCode == 91822)

        .Select(c =>

             new CustomerTuple { Name = c.Name, Address = c.Address });

请注意,对象初始值允许省略构造函数的括号。此外,字段和可设置的属性均可在对象初始值的主体内部进行赋值。

我们现在已经拥有在 C# 中创建查询的简洁语法。尽管如此,我们还有一种可扩展途径,可通过扩展方法以及一组本身非常有用的语言功能来添加新的运算符(Distinct、OrderBy、Sum 等)。

语 言设计团队现在有了数种可赖以获得反馈的原型。因此,我们与许多富于 C# 和 SQL 经验的参与者组织了一项可用性研究。几乎所有反馈都是肯定的,但明显疏忽了某些东西。具体而言,开发人员难以应用他们的 SQL 知识,因为我们认为理想的语法与他们擅长领域的专门技术并不很符合。


查询表达式

于是,语言设计团队设计了一种与 SQL 更为相近的语法,称为查询表达式。例如,针对我们的示例的查询表达式可如下所示:

var locals = from c in customers

             where c.ZipCode == 91822

             select new { FullName = c.FirstName + “ “ +

                          c.LastName, HomeAddress = c.Address };

查询表达式是基于上述语言功能构建而成。它们在语法上,完全转换为我们已经看到的基础语法。例如,上述查询可直接转换为:

var locals =

   customers

       .Where(c => c.ZipCode == 91822)

       .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,

                          HomeAddress = c.Address });

查 询表达式支持许多不同的“子句”,如 from、where、select、orderby、group by、let 和 join。这些子句先转换为对等的运算符调用,后者进而通过扩展方法实现。如果查询语法不支持必要运算符的子句,则查询子句和实现运算符的扩展方法之间的 紧密关系很便于将两者结合。例如:

var locals = (from c in customers

              where c.ZipCode == 91822

              select new { FullName = c.FirstName + “ “ +

                          c.LastName, HomeAddress = c.Address})

             .Count();

在本例中,查询现在返回在 91822 ZIP Code 区居住的客户人数。

通 过该种方法,我们已经设法在结束时达到了开始时的目标(我对这一点始终觉得非常满意)。下一版本的 C# 的语法历经数年时间的发展,尝试了许多新的语言功能,才最终到达近乎于 2004 年冬提议的原始语法的境界。查询表达式的加入以 C# 即将发布的版本的其他语言功能为基础,并促使许多查询情况更便于具有 SQL 背景的开发人员阅读和理解。

[文档]SQL Server 2000 系统表和 SQL Server 2005 系统视图之间的映射

mikel阅读(862)

本主题说明了 SQL Server 2000 系统表和 SQL Server 2005 系统视图之间的映射。

下表将 SQL Server 2000 中 master 数据库内的系统表映射到它们在 SQL Server 2005 中对应的一个或多个系统视图。

系统表 系统视图 视图类型

sysaltfiles

sys.master_files

目录视图

syscacheobjects

sys.dm_exec_cached_plans

动态管理视图

syscharsets

sys.syscharsets

兼容性视图

sysconfigures

sys.configurations

目录视图

syscurconfigs

sys.configurations

目录视图

sysdatabases

sys.databases

目录视图

sysdevices

sys.backup_devices

目录视图

syslanguages

sys.syslanguages

兼容性视图

syslockinfo

sys.dm_tran_locks

动态管理视图

syslocks

sys.dm_tran_locks

动态管理视图

syslogins

sys.server_principals

目录视图

sysmessages

sys.messages

目录视图

sysoledbusers

sys.linked_logins

目录视图

sysopentapes

sys.dm_io_backup_tapes

动态管理视图

sysperfinfo

sys.dm_os_performance_counters

动态管理视图

sysprocesses

sys.dm_exec_connections

sys.dm_exec_sessions

sys.dm_exec_requests

动态管理视图

sysremotelogins

sys.remote_logins

目录视图

sysservers

sys.servers

目录视图

下表将 SQL Server 2000 中每个数据库内的系统表映射到它们在 SQL Server 2005 中对应的一个或多个系统视图。

系统表 系统视图 视图类型

syscolumns

sys.columns

目录视图

syscomments

sys.sql_modules

目录视图

sysconstraints

sys.check_constraints

sys.default_constraints

sys.key_constraints

sys.foreign_keys

目录视图

sysdepends

sys.sql_dependencies

目录视图

sysfilegroups

sys.filegroups

目录视图

sysfiles

sys.database_files

目录视图

sysforeignkeys

sys.foreign_keys

目录视图

sysindexes

sys.indexes

目录视图

sysindexkeys

sys.index_columns

目录视图

sysmembers

sys.database_role_members

目录视图

sysobjects

sys.objects

目录视图

syspermissions

sys.database_permissions

sys.server_permissions

目录视图

sysprotects

sys.database_permissions

sys.server_permissions

目录视图

sysreferences

sys.foreign_keys

目录视图

systypes

sys.types

目录视图

sysusers

sys.database_principals

目录视图

sysfulltextcatalogs

sys.fulltext_catalogs

目录视图

[代码]SQLServer2005读取表信息

mikel阅读(856)

declare @schemaName varchar(100)
declare @tblName varchar(100)
declare @colName varchar(100)
declare @objectID int
set @schemaName = 'College'
set @tblName = 'Student'
set @colName = 'iStatusID'
set @objectID = OBJECT_ID(@schemaName + '.' + @tblName)
— 1. How to check the Column is nullable?
Select COLUMNPROPERTY(@objectID,@colName,'AllowsNull') AS 'Allows Null?';
— 2. How to check the Column is an identity?
Select COLUMNPROPERTY(@objectID,@colName,'IsIdentity') AS 'Identity?';
— 3. How to check the Column is an FullTextEnabled?
Select COLUMNPROPERTY(@objectID,@colName,'IsFulltextIndexed') AS 'FullTextEnabled?';
— 4. How to check the Column's datatype?
select b.name as 'Datatype', a.max_length, a.precision, a.scale
from sys.columns a
join sys.types b on a.system_type_id = b.system_type_id and a.user_type_id = b.user_type_id
where OBJECT_NAME(a.object_id) = @tblName and a.name = @colName
— 5. How to identify that the default constraints have been created for the Column?
select a.name as 'Default Constraint Name'
from sys.default_constraints a
join sys.all_columns b on a.parent_object_id = b.object_id and a.parent_column_id = b.column_id
where object_name(parent_object_id) = @tblName and b.name = @colName
— 6. How to identify that the foreignkey constraints for the table?
select name as 'ForeignKeyConstraint Name' from sys.objects
where type = 'F' and parent_object_id = @objectID
— 7. Select all Constraints associated with this table and Column.
Select Constraint_Name from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
Where Table_Name = @tblName and Column_Name = @colName
— 8. Find all the Objects from sys.objects table by specifying the “type”.
select name from sys.objects Where parent_object_id = @objectID and type = 'D'

[教程]SQL Server 2005:向系统表说再见

mikel阅读(691)

微软的SQL Server 数据库管理员 ,快快想一下!在不使用任何的文档的情况下,编写一个查询,从SQL Server 2000系统表中抽取索引的列表,然后列举每个索引中的字段,并判断这个字段是否按照升序或者降序进行排序。你有两分钟的时间。快!
  
   如果你现在真的停下阅读,开始用必不可少的两分钟时间思考这项不讨好的任务,那么现在你就陷入了一个大麻烦中,这里面涉及了系统索引、系统索引关键字, 系统字段,以及一些元数据函数,其中包括类似OBJECT_NAME 和INDEXKEY_PROPERTY这样的备用信息。到现在为止,要编写这样的一个查询很明显要花费远远超过2分钟的时间了。
  
  不幸的SQL Server 2000数据库管理员们,需要浏览深奥的系统表,这是这项使用数据库管理系统的工作中最糟糕的一部分。系统表,通常是有效率的,但是在我的印象里,它可从来不是为了用户友好设计的。
  
   幸运的是,眼前就有了救星。在SQL Server 2005中,系统表不见了。是的。不见了。再也不需要对陌生的位进行操作,也不需要找出神秘的编码方案——这在过去都是必需的。对于你们中间需要对遗留下 来的参考这些表的人来说,我知道你在想什么:无休止的机械的升级以保障与SQL Server 2005的兼容。但是还不要心生厌恶。系统中仍然存在类似系统表的对象,就是为了向下兼容的目的。但是表的自身是——或者是实际上应该是——被遗忘,像8 -tracks 和 Tab一样被投入了历史的垃圾桶中。
  
  那么这些表去了哪里呢?SQL Server 2005中的系统数据现在存储在隐藏的“资源”表中,这个表只能被服务器自身直接访问。低级用户(和数据库管理员)必须使用新的一系列的分类视图,这些视 图显示了从各种我们看不到也不能调用的隐藏表和各种隐藏函数中获得的数据。以前版本的SQL Server 中的系统表现在作为一系列所谓的(也相当正确的)“兼容视图”的形式实现。
  
  分类视图和它们的伙伴,动态管理视图(下面进行解 释),代表了一种处理元数据的方式,这些元数据是完全重新设计和重新思考出来的。没有了那些只会给数据库管理员一些底层数据的微小感觉的神秘的表,现在的 SQL Server提供了丰富的资源:SQL Server 2005中有超过200个分类和管理视图,取代了以前版本中大约50个的系统表。
  
   所有这些视图都可以在系统计划中找到。(计划是在SQL Server 2005中大大扩展了的安全特性。但是这是另一篇贴士的话题。)要看到可用视图的完全列表,SQL Server Management Studio扩展了所有数据库的系统视图树。或者通过T-SQL 从视图自身选择一个列表,并找出友好的易于理解的名字:
  
  Select name
  
  FROM sys.all_views
  
  Where is_ms_shipped = 1
  
  你还会发现再也不需要通过浏览文档来查找有关做某件关系系统数据的事情的线索。这些视图都有很明确的自我解释。
  
   有关视图名字的一些线索如下:那些前缀是dm_的是动态管理视图,通过类似当前会话、锁,以及系统资源的信息表示服务器的正在改变的状态。其他的视图都 可以认为是分类视图。那些前缀是all_的包含了有关系统对象(例如视图)和用户定义的对象的信息。那些没有all_前缀的只包含了用户定义的对象的信 息。在那些包括了系统对象的视图中,is_ms_shipping字段可用于区分用户定义对象和系统对象。如果is_ms_shipped字段的值为1, 则这一行代表了一个系统对象,否则,就是用户定义的对象。
  
  最后,让我们检查一些你可以从分类视图中获得数据类型。对于初学者,所 有常见的内容都可以获得。例如:查看索引中的数据,使用sys.indexes,而不是原先的sysindexes——奇怪的是,现在称之为 sys.sysindexes。对于约束,试试sys.check_constraints, sys.default_constraints, 或者 sys.key_constraints。看出这个趋势了吗?
  
  这篇贴士哪怕是没有简单的提到一句有关新的动态管理视图的 话,都是不完整的。这些视图是SQL Server存储新的元数据的强有力的工具,它们可以帮助数据库管理员快速解决问题并分析服务器的性能。其中的一些明星选手,包括 sys.dm_exec_query_stats,用来报告查询要求了多少个处理器时间;以及sys.dm_db_index_usage_stats, 用来帮助数据库管理员决定哪一个索引是最有用的,哪些是没有用的。
  
  对于这个巨大的元数据视图集合,还有更多的话需要说。但是现在,可以看看最近由微软发布在网上的beta版的SQL Server 2005在线书籍。系统视图主题提供了对这个强大的新的数据仓库的能力的整体描述。
  
  另外,以下是那个2分钟问题的解决方案。首先使用SQL Server 2000系统表。其次,可以尽早地阅读有关SQL Server 2005 分类视图的译本。
  

 

[文档]SQLServer系统表结构

mikel阅读(956)

sql server系统表详细说明

sysaltfiles  主数据库 保存数据库的文件

syscharsets  主数据库字符集与排序顺序

sysconfigures 主数据库 配置选项

 syscurconfigs 主数据库当前配置选项

  sysdatabases 主数据库服务器中的数据库

  syslanguages 主数据库语言

  syslogins 主数据库 登陆帐号信息

 sysoledbusers 主数据库 链接服务器登陆信息

  sysprocesses 主数据库进程

  sysremotelogins主数据库 远程登录帐号

  syscolumns 每个数据库 列

  sysconstrains 每个数据库 限制

  sysfilegroups 每个数据库 文件组

  sysfiles 每个数据库 文件

  sysforeignkeys 每个数据库 外部关键字

  sysindexs 每个数据库 索引

  sysmenbers 每个数据库角色成员

  sysobjects 每个数据库所有数据库对象

  syspermissions 每个数据库 权限

  systypes 每个数据库 用户定义数据类型

  sysusers 每个数据库 用户

sysaltfiles  页首

在特殊情况下,包含与数据库中的文件相对应的行。该表存储在 master 数据库中。

列名 数据类型 描述
fileid smallint 每个数据库的唯一文件标识号。
groupid smallint 文件组标识号。
size int 文件大小(以 8 KB 页为单位)。
maxsize int 最大文件大小(以 8 KB 页为单位)。0 值表示不增长,–1 值表示文件应一直增长到磁盘已满。
growth int 数据库的增长大小。0 值表示不增长。根据状态的值,可以是页数或文件大小的百分比。如果 status 为 0x100000,则 growth 是文件大小的百分比;否则是页数。
status int 仅限内部使用。
perf int 保留。
dbid smallint 该文件所属数据库的数据库标识号。
name nchar(128) 文件的逻辑名称。
filename nchar(260) 物理设备的名称,包括文件的完整路径。

>syscharsets 页首

每个字符集在表中各占一行,表中还包含定义供 Microsoft? SQL Server? 使用的排序次序。排序次序中的一个在 sysconfigures 中标记为默认排序次序,该次序是实际使用的唯一次序。

列名 数据类型 描述
type smallint 该行表示的实体类型。1001 是字符集;2001 是排序次序。
id tinyint 字符集或排序次序的唯一 ID。注意排序次序和字符集不能共享相同的 ID 号。保留从 1 到 240 的 ID 范围供 SQL Server 使用。
csid tinyint 如果该行表示字符集,则不使用该字段。如果该行表示排序次序,则该字段是在其上生成排序次序的字符集 ID。假设具有该 ID 的字符集行存在于该表中。
status smallint 内部系统状态信息位。
name sysname 字符集或排序次序的唯一名称。该字段必须只包含字母 A-Z 或 a-z、数字 0 – 9 和下划线 (_)。必须以字母开头。
description nvarchar(255) 字符集或排序次序功能的可选描述。
binarydefinition varbinary(255) 仅限内部使用。
definition image 字符集或排序次序的内部定义。该字段中的数据结构取决于类型。

sysconfigures 页首

用户设置的每个配置选项在表中各占一行。 sysconfigures 包含最近启动 Microsoft? SQL Server? 前定义的配置选项,还包含最近启动后设置的所有动态配置选项。该表只位于 master 数据库中。

列名 数据类型 描述
value int 变量的用户可修改值(仅在已执行 RECONFIGURE 后由 SQL Server 使用)。
config smallint 配置变量号。
comment nvarchar(255) 对配置选项的解释。
status smallint 表示选项状态的位图。可能的值包括:

0 = 静态(该设置在服务器重新启动时生效)。
1 = 动态(该变量在 RECONFIGURE 语句执行时生效)。
2 = 高级(仅当设置了显示高级选项时才显示该变量)。
3 = 动态和高级。

syscurconfigs 页首

每个当前配置选项各占一项。另外,该表还包含四个描述配置结构的项。 syscurconfigs 在由用户查询时动态生成。有关更多信息,请参见 sysconfigures

列名 数据类型 描述
value int 用户可修改的变量值(仅在已执行 RECONFIGURE 的情况下由 Microsoft? SQL Server? 使用)。
config smallint 配置变量号。
comment nvarchar(255) 对配置选项的解释。
status smallint 表示选项状态的位图。可能的值包括:

0 = 静态(该设置在服务器重新启动时生效)。
1 = 动态(该变量在 RECONFIGURE 语句执行时生效)。
2 = 高级(仅当设置了显示高级选项时才显示该变量)。
3 = 动态和高级。

 

sysdatabases 页首

Microsoft? SQL Server? 上的每个数据库在表中占一行。最初安装 SQL Server 时, sysdatabases 包含 master model msdb mssqlwebtempdb 数据库的项。该表只存储在 master 数据库中。

列名 数据类型 描述
name sysname 数据库的名称。
dbid smallint 数据库 ID。
sid varbinary(85) 数据库创建者的系统 ID。
mode smallint 用于创建数据库时在内部锁定该数据库。
status int 状态位,其中某些状态位可由用户使用 sp_dboption read only dbo use only single user 等)进行设置:

1 = autoclose ;使用 sp_dboption 设置。
4 = select into/bulkcopy ;使用 sp_dboption 设置。
8 = trunc. log on chkpt ;使用 sp_dboption 设置。
16 = torn page detection ,使用 sp_dboption 设置。
32 = loading
64 = pre recovery
128 = recovering
256 = not recovered
512 = offline ;使用 sp_dboption 设置。
1024 = read only ;使用 sp_dboption 设置。
2048 = dbo use only ;使用
sp_dboption 设置。
4096 = single user ;使用 sp_dboption 设置。
32768 = emergency mode
4194304 = autoshrink
1073741824 = cleanly shutdown

可以同时打开多个位。

status2 int 16384 = ANSI null default ;使用 sp_dboption 设置。
65536 = concat null yields null ,使用 sp_dboption 设置。
131072 = recursive triggers ,使用 sp_dboption 设置。
1048576 = default to local cursor ,使用 sp_dboption 设置。
8388608 = quoted identifier ,使用
sp_dboption 设置。
33554432 = cursor close on commit ,使用 sp_dboption 设置。
67108864 = ANSI nulls ,使用 sp_dboption 设置。
268435456 = ANSI warnings ,使用 sp_dboption 设置。
536870912 = full text enabled ,使用
sp_fulltext_database
设置。
crdate datetime 创建日期。
reserved datetime 留作以后使用。
category int 包含用于复制的信息位图:

1 = 已发布。
2 = 已订阅。
4 = 合并已发布。
8 = 合并已订阅。

cmptlevel tinyint 数据库的兼容级别。有关更多信息,请参见 sp_dbcmptlevel
filename nvarchar(260) 数据库主文件的操作系统路径和名称。
version smallint 创建数据库时使用的 SQL Server 代码内部版本号。仅供 SQL Server 工具在内部用于升级处理。

syslanguages 页首

出现在 Microsoft? SQL Server? 中的每种语言在表中各占一行。虽然美国英语不在 syslanguages 内,但该表始终可由 SQL Server 使用。该表只存储在 master 数据库中。

列名 数据类型 描述
langid smallint 唯一语言 ID。
dateformat nchar(3) 日期顺序(如 DMY)。
datefirst tinyint 一周的第一天:1 表示星期一,2 表示星期二,依此类推,直到 7 表示星期日。
upgrade int 留作系统使用。
name sysname 正式语言名称(例如,fran?ais)。
alias sysname 备用语言名称(如 French)。
months nvarchar(372) 按从一月到十二月的顺序排列的用逗号分隔的月份全称列表,每个名称最多包含 20 个字符。
shortmonths varchar(132) 按从一月到十二月的顺序排列的用逗号分隔的缩写月份名称列表,每个名称最多包含 9 个字符。
days nvarchar(217) 按从一月到十二月的顺序排列的用逗号分隔的天名称列表,每个名称最多包含 30 个字符。
lcid int 此种语言的 Microsoft Windows NT? 区域设置 ID。
mslangid smallint SQL Server 消息组 ID。

安装了 SQL Server 提供的三十三种语言。下面是语言列表。

用英语表示的名称 NT LCID SQL Server 消息组 ID
English 1033 1033
German 1031 1031
French 1036 1036
Japanese 1041 1041
Danish 1030 1030
Spanish 3082 3082
Italian 1040 1040
Dutch 1043 1043
Norwegian 2068 2068
Portuguese 2070 2070
Finnish 1035 1035
Swedish 1053 1053
Czech 1029 1029
Hungarian 1038 1038
Polish 1045 1045
Romanian 1048 1048
Croatian 1050 1050
Slovak 1051 1051
Slovene 1060 1060
Greek 1032 1032
Bulgarian 1026 1026
Russian 1049 1049
Turkish 1055 1055
British English 2057 1033
Estonian 1061 1061
Latvian 1062 1062
Lithuanian 1063 1063
Brazilian 1046 1046
Traditional Chinese 1028 1028
Korean 1042 1042
Simplified Chinese 2052 2052
Arabic 1025 1025
Thai 1054 1054

syslogins 页首

每个登录帐户在表中占一行。

列名 数据类型 描述
sid varbinary(85) 安全标识符。
status smallint 仅限内部使用。
createdate datetime 添加登录的日期。
updatedate datetime 更新登录的日期。
accdate datetime 仅限内部使用。
totcpu int 仅限内部使用。
totio int 仅限内部使用。
spacelimit int 仅限内部使用。
timelimit int 仅限内部使用。
resultlimit int 仅限内部使用。
name varchar(30) 用户的登录 ID。
dbname nvarchar(128) 建立连接时,用户的默认数据库名。
password nvarchar(128) 用户的加密密码(可以是 NULL)。
language nvarchar(128) 用户的默认语言。
denylogin int 如果登录是 Microsoft? Windows NT? 用户或组且已被拒绝访问,则为 1。
hasaccess int 如果已授权登录访问服务器,则为 1。
isntname int 如果登录是 Windows NT 用户或组,则为 1;如果登录是 Microsoft SQL Server? 登录,则为 0。
isntgroup int 如果登录是 Windows NT 组,则为 1。
isntuser int 如果登录是 Windows NT 用户,则为 1。
sysadmin int 如果登录是 sysadmin 服务器角色成员,则为 1。
securityadmin int 如果登录是 securityadmin 服务器角色成员,则为 1。
serveradmin int 如果登录是 serveradmin 固定服务器角色成员,则为 1。
setupadmin int 如果登录是 setupadmin 固定服务器角色成员,则为 1。
processadmin int 如果登录是 processadmin 固定服务器角色成员,则为 1。
diskadmin int 如果登录是 diskadmin 固定服务器角色成员,则为 1。
dbcreator int 如果登录是 dbcreator 固定服务器角色成员,则为 1。
loginname nvarchar(128) 登录的实际名称,该名称可能不同于 SQL Server 所使用的登录名。

sysoledbusers 页首

每个指定的链接服务器的用户和密码映射在表中占一行。该表存储在 master 数据库中。

列名 数据类型 描述
rmtsrvid smallint 服务器的 SID(安全标识号)。
rmtloginame nvarchar(128) loginsid 映射到的链接 rmtservid 的远程登录名。
rmtpassword nvarchar(128) 链接 rmtsrvid 内的指定远程登录的加密密码。
loginsid varbinary(85) 要映射的本地登录 SID。
status smallint 如果该值为 1,映射应使用用户自己的凭据。
changedate datetime 上次更改映射信息的日期。

sysprocesses  页首

sysprocesses 表中保存关于运行在 Microsoft? SQL Server? 上的进程的信息。这些进程可以是客户端进程或系统进程。 sysprocesses 只存储在 master 数据库中。

列名 数据类型 描述
spid smallint SQL Server 进程 ID。
kpid smallint Microsoft Windows NT 4.0? 线程 ID。
blocked smallint 分块进程的进程 ID ( spid )。
waittype binary(2) 保留。
waittime int 当前等待时间(以毫秒为单位)。当进程不处于等待时,为 0。
lastwaittype nchar(32) 表示上次或当前等待类型名称的字符串。
waitresource nchar(32) 锁资源的文本化表示法。
dbid smallint 当前正由进程使用的数据库 ID。
uid smallint 执行命令的用户 ID。
cpu int 进程的累计 CPU 时间。无论 SET STATISTICS TIME ON 选项是 ON 还是 OFF,都为所有进程更新该条目。
physical_io int 进程的累计磁盘读取和写入。
memusage int 当前分配给该进程的过程高速缓存中的页数。一个负数,表示进程正在释放由另一个进程分配的内存。
login_time datetime 客户端进程登录到服务器的时间。对于系统进程,是存储 SQL Server 启动发生的时间。
last_batch datetime 客户端进程上次执行远程存储过程调用或 EXECUTE 语句的时间。对于系统进程,是存储 SQL Server 启动发生的时间。
ecid smallint 用于唯一标识代表单个进程进行操作的子线程的执行上下文 ID。
open_tran smallint 进程的打开事务数。
status nchar(30) 进程 ID 状态(如运行、休眠等)。
sid binary(85) 用户的全局唯一标识符 (GUID)。
hostname nchar(128) 工作站的名称。
program_name nchar(128) 应用程序的名称。
hostprocess nchar(8) 工作站进程 ID 号。
cmd nchar(16) 当前正在执行的命令。
nt_domain nchar(128) 客户端的 Windows NT 4.0 域(如果使用 Windows 身份验证)或信任连接的 Windows NT 4.0 域。
nt_username nchar(128) 进程的 Windows NT 4.0用户名(如果使用 Windows 身份验证)或信任连接的 Windows NT 4.0 用户名。
net_address nchar(12) 指派给每个用户工作站上的网络接口卡唯一标识符。当用户登录时,该标识符插入 net_address 列。
net_library nchar(12) 用于存储客户端网络库的列。每个客户端进程都在网络连接上进入。网络连接有一个与这些进程关联的网络库,该网络库使得这些进程可以建立连接。有关更多信息,请参见客户端和服务器 Net-Library
loginame nchar(128) 登录名。

sysremotelogins 页首

每个允许调用 Microsoft? SQL Server? 上的远程存储过程的远程用户占一行。

列名 数据类型 描述
remoteserverid smallint 远程服务器标识。
remoteusername nvarchar(128) 远程服务器上的用户登录名。
status smallint 选项的位图。
sid varbinary(85) Microsoft Windows NT? 用户安全 ID。
changedate datetime 添加远程用户的日期和时间。

syscolumns 页首

每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行。该表位于每个数据库中。

列名 数据类型 描述
name sysname 列名或过程参数的名称。
id int 该列所属的表对象 ID,或与该参数关联的存储过程 ID。
xtype tinyint systypes 中的物理存储类型。
typestat tinyint 仅限内部使用。
xusertype smallint 扩展的用户定义数据类型 ID。
length smallint systypes 中的最大物理存储长度。
xprec tinyint 仅限内部使用。
xscale tinyint 仅限内部使用。
colid smallint 列或参数 ID。
xoffset smallint 仅限内部使用。
bitpos tinyint 仅限内部使用。
reserved tinyint 仅限内部使用。
colstat smallint 仅限内部使用。
cdefault int 该列的默认值 ID。
domain int 该列的规则或 CHECK 约束 ID。
number smallint 过程分组时(0 表示非过程项)的子过程号。
colorder smallint 仅限内部使用。
autoval varbinary(255) 仅限内部使用。
offset smallint 该列所在行的偏移量;如果为负,表示可变长度行。
status tinyint 用于描述列或参数属性的位图:

0x08 = 列允许空值。
0x10 = 当添加 varcharvarbinary 列时,ANSI 填充生效。保留 varchar 列的尾随空格,保留 varbinary 列的尾随零。
0x40 = 参数为 OUTPUT 参数。
0x80 = 列为标识列。

type tinyint systypes 中的物理存储类型。
usertype smallint systypes 中的用户定义数据类型 ID。
printfmt varchar(255) 仅限内部使用。
prec smallint 该列的精度级别。
scale int 该列的小数位数。
iscomputed int 表示是否已计算该列的标志:

0 = 未计算。
1 = 已计算。

isoutparam int 表示该过程参数是否是输出参数:

1 = 真。
0 = 假。

isnullable int 表示该列是否允许空值:

1 = 真。
0 = 假。

sysconstraints 页首

包含约束映射,映射到拥有该约束的对象。该系统目录存储在每个数据库中。

列名 数据类型 描述
constid int 约束号。
id int 拥有该约束的表 ID。
colid smallint 在其上定义约束的列 ID,如果是表约束则为 0。
spare1 tinyint 保留。
status int 位图指示状态。可能的值包括:

1 = PRIMARY KEY 约束。
2 = UNIQUE KEY 约束。
3 = FOREIGN KEY 约束。
4 = CHECK 约束。
5 = DEFAULT 约束。
16 = 列级约束。
32 = 表级约束。

actions int 保留。
error int 保留。

sysfilegroups 页首

数据库中的每个文件组在表中占一行。该表存储在每个数据库中。在该表中至少有一项用于主文件组。

列名 数据类型 描述
groupid smallint 每个数据库的唯一组标识号。
allocpolicy smallint 保留。
status int 0x8 = READ ONLY
0x10 = DEFAULT
groupname sysname 文件组的名称。

sysfiles 页首

数据库中的每个文件在表中占一行。该系统表是虚拟表,不能直接更新或修改。

列名 数据类型 描述
fileid smallint 每个数据库的唯一文件标识号。
groupid smallint 文件组标识号。
size int 文件大小(以 8 KB 页为单位)。
maxsize int 最大文件大小(以 8 KB 页为单位)。0 值表示不增长,–1 值表示文件应一直增长到磁盘已满。
growth int 数据库的增长大小。0 值表示不增长。根据状态的值,可以是页数或文件大小的百分比。如果 status 包含 0x100000,则 growth 是文件大小的百分比;否则,它是页数。
status int growth 值(以兆字节 (MB) 或千字节 (KB) 为单位)的状态位。

0x1 = 默认设备。
0x2 = 磁盘文件。
0x40 = 日志设备。
0x80 = 自上次备份后已写入文件。
0x4000 = 由 Create DATABASE 语句
隐性创建的设备。
0x8000 = 在数据库创建过程中创建的设备。
0x100000 = 按百分比而不是按页数增长。

perf int 保留。
name nchar(128) 文件的逻辑名称。
filename nchar(260) 物理设备的名称,包括文件的完整路径。

sysforeignkeys 页首

包含关于表定义中的 FOREIGN KEY 约束的信息。该表存储在每个数据库中。

列名 数据类型 描述
constid int FOREIGN KEY 约束的 ID。
fkeyid int 具有 FOREIGN KEY 约束的表对象 ID。
rkeyid int 在 FOREIGN KEY 约束中引用的表对象 ID。
fkey smallint 正在引用的列 ID。
rkey smallint 已引用的列 ID。
keyno smallint 该列在引用列列表中的位置。

sysindexes 页首

数据库中的每个索引和表在表中各占一行。该表存储在每个数据库中。

列名 数据类型 描述
id int 表 ID(如果 indid = 0 或 255)。否则为索引所属表的 ID。
status int 内部系统状态信息。
first binary(6) 指向第一页或根页的指针。
indid smallint 索引 ID:

1 = 聚集索引
>1 = 非聚集
255 = 具有 text image 数据的表条目

root binary(6) 如果 indid >= 1 和 < 255, root 是指向根页的指针。如果 indid = 0 或 indid = 255, root 是指向最后一页的指针。
minlen smallint 最小行大小。
keycnt smallint 键的数目。
groupid smallint 在其上创建对象的文件组 ID。
dpages int 如果 indid = 0 或 indid = 1, dpages 是已用数据页的计数。如果 indid = 255,其设置为 0。否则是已用索引页的计数。
reserved int 如果 indid = 0 或 indid = 1, reserved 是分配给所有索引和表数据的页计数。如果 indid = 255, reserved 是分配给 textimage 数据的页计数。否则是分配给索引的页计数。
used int 如果 indid = 0 或 indid = 1, used 是用于所有索引和表数据的总页数。如果 indid = 255, used 是用于 textimage 数据的页计数。否则是用于索引的页计数。
rowcnt bigint 基于 indid = 0 和 indid = 1 的数据级行计数。如果 indid = 255, rowcnt 设置为 0。
rowmodctr int 对自上次更新表的统计后插入、删除或更新行的总数进行计数。
xmaxlen smallint 最大行大小。
maxirow smallint 最大非叶索引行大小。
OrigFillFactor tinyint 创建索引时使用的起始填充因子值。不保留该值;然而,如果需要重新创建索引但记不住当初使用的填充因子,则该值可能很有帮助。
reserved1 tinyint 保留。
reserved2 int 保留。
FirstIAM binary(6) 保留。
impid smallint 保留。索引实现标志。
lockflags smallint 用于约束经过考虑的索引锁粒度。例如,对于本质上是只读的查找表,可以将其设置为仅进行表级锁定以使锁定成本减到最小。
pgmodctr int 保留。
keys varbinary(816) 组成索引键的列 ID 列表。
name sysname 表名(如果 indid = 0 或 255)。否则为索引的名称。
statblob image 统计 BLOB。
maxlen int 保留。
rows int 基于 indid = 0 和 indid = 1的数据级行数,该值对于 indid >1 重复。如果 indid = 255, rows 设置为 0。提供该列是为了向后兼容。

sysmembers  页首

每个数据库角色成员在表中占一行。该表存储在每个数据库中。

列名 数据类型 描述
memberuid smallint 角色成员的用户 ID。
groupuid smallint 角色的用户 ID。

sysobjects 页首

在数据库内创建的每个对象(约束、默认值、日志、规则、存储过程等)在表中占一行。只有在 tempdb 内,每个临时对象才在该表中占一行。

列名 数据类型 描述
name sysname 对象名。
Id int 对象标识号。
xtype char(2) 对象类型。可以是下列对象类型中的一种:

C = CHECK 约束
D = 默认值或 DEFAULT 约束
F = FOREIGN KEY 约束
L = 日志
FN = 标量函数
IF = 内嵌表函数
P = 存储过程
PK = PRIMARY KEY 约束(类型是 K)
RF = 复制筛选存储过程
S = 系统表
TF = 表函数
TR = 触发器
U = 用户表
UQ = UNIQUE 约束(类型是 K)
V = 视图
X = 扩展存储过程

uid smallint 所有者对象的用户 ID。
info smallint 保留。仅限内部使用。
status int 保留。仅限内部使用。
base_schema_
ver
int 保留。仅限内部使用。
replinfo int 保留。供复制使用。
parent_obj int 父对象的对象标识号(例如,对于触发器或约束,该标识号为表 ID)。
crdate datetime 对象的创建日期。
ftcatid smallint 为全文索引注册的所有用户表的全文目录标识符,对于没有注册的所有用户表则为 0。
schema_ver int 版本号,该版本号在每次表的架构更改时都增加。
stats_schema_
ver
int 保留。仅限内部使用。
type char(2) 对象类型。可以是下列值之一:

C = CHECK 约束
D = 默认值或 DEFAULT 约束
F = FOREIGN KEY 约束
FN = 标量函数
IF = 内嵌表函数
K = PRIMARY KEY 或 UNIQUE 约束
L = 日志
P = 存储过程
R = 规则
RF = 复制筛选存储过程
S = 系统表
TF = 表函数
TR = 触发器
U = 用户表
V = 视图
X = 扩展存储过程

userstat smallint 保留。
sysstat smallint 内部状态信息。
indexdel smallint 保留。
refdate datetime 留作以后使用。
version int 留作以后使用。
deltrig int 保留。
instrig int 保留。
updtrig int 保留。
seltrig int 保留。
category int 用于发布、约束和标识。
cache smallint 保留。

syspermissions  页首

包含有关对数据库内的用户、组和角色授予和拒绝的权限的信息。该表存储在每个数据库中。

列名 数据类型 描述
id int 对象权限的对象 ID;0 表示语句权限。
grantee smallint 受权限影响的用户、组或角色的 ID。
grantor smallint 被授予或废除权限的用户、组或角色的 ID。
actadd smallint 仅限内部使用。
actmod smallint 仅限内部使用。
seladd varbinary(4000) 仅限内部使用。
selmod varbinary(4000) 仅限内部使用。
updadd varbinary(4000) 仅限内部使用。
updmod varbinary(4000) 仅限内部使用。
refadd varbinary(4000) 仅限内部使用。
refmod varbinary(4000) 仅限内部使用。

systypes  页首

对于每种系统提供数据类型和用户定义数据类型,均包含一行信息。该表存储在每个数据库中。

这些是系统提供的数据类型及其 ID 号。

列名 数据类型 描述
name sysname 数据类型名称。
xtype tinyint 物理存储类型。
status tinyint 仅限内部使用。
xusertype smallint 扩展用户类型。
length smallint 数据类型的物理长度。
xprec tinyint 服务器所使用的内部精度。(不能在查询中使用。)
xscale tinyint 服务器所使用的内部小数位数。(不能在查询中使用。)
tdefault int 对此数据类型进行完整性检查的存储过程的 ID。
domain int 对此数据类型进行完整性检查的存储过程的 ID。
uid smallint 数据类型创建者的用户 ID。
reserved smallint 仅限内部使用。
usertype smallint 用户类型 ID。
variable bit 可变长度数据类型为 1;否则为 0。
allownulls bit 指出此数据类型的默认为空性。如果 Create 或 Alter TABLE 指定了为空性,那么该值将替代此数据类型的默认为空性。
type tinyint 物理存储数据类型。
printfmt varchar(255) 保留。
prec smallint 此数据类型的精度级别。
scale tinyint 此数据类型的小数位数(根据精度)。

sysusers 页首

数据库中每个 Microsoft? Windows 用户、Windows 组、Microsoft SQL Server? 用户或 SQL Server 角色在表中占一行。

列名 数据类型 描述
uid smallint 用户 ID,在此数据库中是唯一的。1 是数据库所有者。
status smallint 仅限内部使用。
Name sysname 用户名或组名,在此数据库中是唯一的。
sid varbinary(85) 此条目的安全性标识符。
roles varbinary(2048) 仅限内部使用。
createdate datetime 帐户的添加日期。
updatedate datetime 帐户的上次修改日期。
altuid smallint 仅限内部使用。
password varbinary(256) 仅限内部使用。
gid smallint 此用户所属的组 ID。如果 uid = gid ,那么此条目就定义一个组。
environ varchar(255) 保留。
hasdbaccess int 如果该帐户有数据库访问权限,则为 1。
islogin int 如果该帐户是有登录帐户的 Windows 组、Windows 用户或 SQL Server 用户,则为 1。
isntname int 如果该帐户是 Windows 组或 Windows 用户,则为 1。
isntgroup int 如果该帐户是 Windows 组,则为 1。
isntuser int 如果该帐户是 Windows 用户,则为 1。
issqluser int 如果该帐户是 SQL Server 用户,则为 1。
isaliased int 如果该帐户以另一个用户为别名,则为 1。
issqlrole int 如果该帐户是 SQL Server 角色,则为 1。
isapprole int 如果该帐户是应用程序角色,则为 1。

[教程]ADO.Net2.0架构

mikel阅读(969)

ADO.NET 2.0 中的架构

发布日期 : 09/19/2004 | 更新日期 : 09/19/2004

Bob Beauchemin
DevelopMentor

适用于:
Microsoft ADO.NET 2.0
Microsoft Visual Studio 2005
C# 编程语言

摘要:了解在 ADO.NET 中对于从您的数据源访问元数据的增强支持。

下载相关的 SchemasSample.exe 示例代码。

本页内容

深入了解新的公共元数据 API 深入了解新的公共元数据 API
究竟谁需要元数据? 究竟谁需要元数据?
我能得到什么样的元数据? 我能得到什么样的元数据?
Restrictions Restrictions
DataSourceInformation DataSourceInformation
自定义并扩展元数据 自定义并扩展元数据
用户自定义 用户自定义
小结:元数据支持的最终部分 小结:元数据支持的最终部分

深入了解新的公共元数据 API

我的前一篇文章, 我指出 Visual Studio 2005 服务器资源管理器现在使用一个包含了 .NET 数据提供程序(而不是 OLE DB 提供程序)列表的对话框来提示连接信息。当您确定一个连接字符串并添加数据连接时,每个数据连接也显示一个关于通过连接直接可见的数据库对象(如表、视图 和存储过程)的信息的树形结构。但这些信息来自哪里呢?难道是 Visual Studio 仅为某些数据提供程序硬编码来生成这个信息,而假如我编写我自己的数据提供程序或者从第三方购买一个的时候,就留给我一个空节点?不,在 Visual Studio 2005 中并不是这样。由于 ADO.NET 2.0 中的新架构 API,所有这些有用的信息都将提供给您。我不知道这是否是 Visual Studio 做到它的方法,但是这里就是使用新的 API 来获得一个数据库中的表的列表的代码。

// uses a ADO.NET 2.0 named connection string in config file
// uses ADO.NET 2.0 ProviderFactory and base classes
// see previous article
public static void GetListOfTables(string connectstring_name)
{
ConnectionStringSettings s =
ConfigurationSettings.ConnectionStrings[connectstring_name];
DbProviderFactory f = DbProviderFactories.GetFactory(s.ProviderName);
using (DbConnection conn = f.CreateConnection())
{
conn.ConnectionString = s.ConnectionString;
conn.Open();
DataTable t = conn.GetSchema("Tables");
t.WriteXml("tables.xml");
}
}

究竟谁需要元数据?

元 数据是每个数据访问 API 的一部分。尽管元数据的主要使用者是像 Visual Studio 这样的工具或者像 DeKlarit 这样的代码生成器,但是它们并不是惟一的使用者。应用程序包设计师可能允许最终用户通过向现有的表添加新表或新列来自定义一个应用程序。当最终用户如此改 变了数据库架构时,一个通用查询和修改工具可以在维护、备份和其他应用程序函数中使用元数据来包含用户的新表,就像它们是应用程序附带的内置表一样。程序 员可以使用元数据来编写他们自己的派生自 System.Data.Common.DbCommandBuilder的自定义类,并为使用 DataSet 创建插入、更新和删除命令。多数据库应用程序(即设计为在用户选择的数据库上运行的应用程序)的构建者可以尽可能多地使用元数据来维护公共代码库,在需要时优化数据访问代码。

通过一般元数据 API 来公开元数据要比让每个使用者使用特定于数据库的 API 要好。这样,工具编写人员可以维护一个可管理性更好的代码库。这样的 API 还必须是非常灵活的,因为在编写一般 API 来公开元数据时有四个障碍需要考虑。

  1. 元数据集合和信息在数据库间是有差别的。例如,SQL Server 用户可能想要公开一个链接服务器的集合,但是 oracle 用户可能对关于 oracle 序列的信息感兴趣。

  2. 不仅在不同的数据库产品中,而且即使在相同数据库的不同版本中,存储公共数据库元数据的基础系统表都是不同的。例如,SQL Server 2005 使用在一个“sys”架构下的新表(例如,sys.tables)公开它的元数据,而 SQL Server 以前的版本使用元数据表(如 sysobjects£©来存储相同的数据。

  3. 不同的程序可能有不同的元数据视图。以一个例子来说,许多程序员抱怨 oracle 数据库中表的列表太长,因为大多数元数据 API 将“system”表与用户表混在一起。他们想要一个仅由他们定义的表组成的短列表。

  4. 是否根本不支持元数据,要提供多少元数据,应该完全取决于提供程序的编写者。

大 部分数据库 API 提供一个标准的元数据集,它是所有提供程序必须支持的,并且允许提供程序编写者添加新的元数据表。这与使用 ANSI SQL 标准采用的方法是一致的。解决这一问题的标准的一部分是 Schema Schemata(INFORMATION_SCHEMA 和 DEFINITION_SCHEMA)的第 11 部分。ANSI SQL INFORMATION_SCHEMA 定义了由一个兼容的数据库支持的标准的元数据视图集。但即便是这个规范也需要有一个方法来解决上面这些问题。它声明:

“实施者可以自由添加额外的表到 INFORMATION_SCHEMA 或添加额外的列到预定义的INFORMATION_SCHEMA 表。”

OLE DB 作为一个与 ANSI SQL 标准概念一致的数据访问 API 示例,定义了一系列的名为“架构行集合”的元数据。它从一个大致遵循 INFORMATION_SCHEMA 的预定义集开始,并添加 OLE DB 特定的列到每个行中。ADO.NET 2.0 提供了一个甚至更强大更灵活的机制来公开元数据。

我能得到什么样的元数据?

ADO.NET 2.0 允许提供程序编写者公开 5 种不同类型的元数据。这些主要的元数据 — “元数据集合”或“类别” — 在 System.Data.Common.DbMetaDataCollectionNames 类中被枚举出来。

  • MetaDataCollections — 可用元数据集合的列表。

  • Restrictions — 对于每个元数据集合,存在一批可以用于限制被请求的架构信息范围的限定符。

  • DataSourceInformation — 关于数据提供程序引用的数据库实例的信息。

  • DataTypes — 一组关于数据库支持的每个数据类型的信息。

  • ReservedWords — 适用于该种数据库查询语言的保留字。通常“查询语言”等同于一种 SQL 的方言。

MetaDataCollections 是 INFORMATION_SCHEMA 集合的名称,如“表”、“列”或“主键”。但是,如果使用 DbConnection.GetSchema,这些元数据类别也被认为是元数据。这意味着在代码方面来说是这样,这些集合可以像普通的元数据一样被获得。

// gets information about database Views
Table t1 = conn.GetSchema("Views");
// gets information about collections exposed by this provider
// this includes the five "meta-collections" described above
Table t2 = conn.GetSchema(DbMetaDataCollectionNames.MetaDataCollections);
// gets information about the Restrictions meta-collection
Table t3 = conn.GetSchema(DbMetaDataCollectionNames.Restrictions);
// No argument overload is same as asking for MetaDataCollections
Table t4 = conn.GetSchema();

5 个元数据集合中的 2 个值得进一步解释。

Restrictions

Restrictions 可以用来限制返回元数据的数量。如果您熟悉 OLE DB 或 ADO,那么术语“restriction”意味着在那些 API 中同样的内容。作为示例,让我们使用 MetaDataCollection“列”,它是表中的列名称的集合。这个集合可以用于获取所有表中的所有列。但是,此被请求的列集合会被数据库名称、 所有者/架构或者表限制。每个元数据集合可以有不同数量的可能限制,并且每个限制会有一个默认值。在我们下面的示例中,这里是一个对列元数据的限制的 XML 表示:

清单 1. 列集合上的 Restrictions(XML 格式)

<Restrictions>
<CollectionName>Columns</CollectionName>
<RestrictionName>Catalog</RestrictionName>
<RestrictionDefault>table_catalog</RestrictionDefault>
<RestrictionNumber>1</RestrictionNumber>
</Restrictions> <Restrictions>
<CollectionName>Columns</CollectionName>
<RestrictionName>Owner</RestrictionName>
<RestrictionDefault>table_schema</RestrictionDefault>
<RestrictionNumber>2</RestrictionNumber>
</Restrictions> <Restrictions>
<CollectionName>Columns</CollectionName>
<RestrictionName>Table</RestrictionName>
<RestrictionDefault>table_name</RestrictionDefault>
<RestrictionNumber>3</RestrictionNumber>
</Restrictions> <Restrictions>
<CollectionName>Columns</CollectionName>
<RestrictionName>Column</RestrictionName>
<RestrictionDefault>column_name</RestrictionDefault>
<RestrictionNumber>4</RestrictionNumber>
</Restrictions>

Restrictions 是使用一个重载的 DbConnection.GetSchema 指定的。这些限制被指定为一个数组。您可以将一个数组指定为和整个限制集合或者一个子集数组一样大,因为“RestrictionNumbers”通常从 最少限制向最多限制发展。对您想要省略的限制值使用空值(不是数据库 NULL,而是 .NET NULL,或者在 Visual Basic .NET 中的 Nothing)。例如:

// restriction string array
string[] res = new string[4];
// all columns, all tables owned by dbo
res[1] = "dbo";
DataTable t1 = conn.GetSchema("Columns", res);
// clear collection
for (int i = 0; i < 4; i++) res[i] = null;
// all columns, all tables named "authors", any owner/schema
res[2] = "authors";
DataTable t2 = conn.GetSchema("Columns", res);
// clear collection
for (int i = 0; i < 4; i++) res[i] = null;
// columns named au_lname
// all tables named "authors", any owner/schema
res[2] = "authors";  res[3] = "au_lname";
DataTable t3 = conn.GetSchema("Columns", res);
// clear collection
for (int i = 0; i < 4; i++) res[i] = null;
// columns named au_lname
// any tables, any owner/schema
res[3] = "name";
DataTable t4 = conn.GetSchema("Columns", res);

您无需指定整个限制数组。在上面的情况中,这里您只想看到“dbo”拥有的表中的列,您可以指定一个只带有两个而不是全部四个成员的 数组。也请注意,将一个空字符串指定为一个限制与指定一个 null(在 Visual Basic .NET 中为 Nothing)值是不同的。您不必记住这些限制,您始终可以查询它们,就像任何其他集合一样。“Restrictions”集合本身不允许限制,但是因 为信息被提取到 DataTable 中,所以您可以使用一个 DataView 来提供相似的功能,如下所示。

DataTable tv = conn.GetSchema(DbMetaDataCollectionNames.Restrictions);
DataView v = tv.DefaultView;
// show restrictions on the "Columns" collection, sorted by number
v.RowFilter = "CollectionName = 'Columns'";
v.Sort = "RestrictionNumber";
for (int i = 0; i < tv.Count; i++)
Console.WriteLine("{0} (default){1}",
tv.Rows[i]["RestrictionName"],
tv.Rows[i]["RestrictionDefault"]);

DataSourceInformation

DataSourceInformation 集合为查询生成器提供关于当前数据库(数据源)实例的信息。虽然这个集合可包含提供程序需要的任何内容,但在 Microsoft 提供程序 (SqlClient、OracleClient、OleDb、Odbc) 中,这个集合包含相似的信息。这里是您默认获得的信息。

表 1. 在 Microsoft 提供程序中的 DataSourceInformation

格式/意义

CompositeIdentifierSeparatorPattern

多部分名称的分隔符(如 pubs.dbo.authors 中的点)

DataSourceProductName

数据库名称

DataSourceProductVersion

数据库版本。请注意这是当前通过 DbConnection 访问的数据库实例的版本。

DataSourceProductVersionNormalized

?

GroupByBehavior

枚举,System.Data.Common.GroupByBehavior

IdentifierPattern

正则表达式字符串

IdentifierCase

枚举,System.Data.Common.IdentifierCase

OrderByColumnsInSelect

布尔值,默认情况下您应该在一个 Select 语句中 orDER BY 这些列

ParameterMarkerFormat

说明参数标记是否以一个特殊的字符开始(如 T-SQL 中的 @)

ParameterMarkerPattern

用于创建参数的正则表达式字符串

ParameterNameMaxLength

参数的最大长度

ParameterNamePattern

用于创建参数的正则表达式字符串

QuotedIdentifierPattern

用于引用标识符的正则表达式字符串

QuotedIdentifierCase

枚举,System.Data.Common.IdentifierCase

StatementSeparatorPattern

正则表达式字符串

StringLiteralPattern

正则表达式字符串

SupportedJoinOperators

枚举,System.Data.Common.SupportedJoinOperators

对特定的数据库方言来说有太多的信息来产生 SQL 了,您不这样认为么?还有一条信息我想要说一下,那就是提供程序是否在参数化查询中使用命名参数或者位置参数。在我关于编写独立于提供程序的代码的上一篇文章中,我将命名和位置参数作为编写参数化命令的两种方法来讨论。

自定义并扩展元数据

既 然我们已经看到了提供的基础元数据并且可以围绕 DbConnection.GetSchema() 找到我们的方法,让我们讨论提供程序编写者使用简单的声明性格式自定义元数据的方法,以及程序员如何能够挂钩到那种格式中。这个讨论与文章开始的元数据复 杂性相关:如何提供独立于数据库版本的元数据以及如何处理不同使用者可能需要相同元数据的不同视图的事实。

首先,让我们指出元数据支持完全是可选的。提供程序不必支持 DbConnection.GetSchema, 这种方法会引发 NotSupportedException。此外,如果提供程序编写者选择支持 DbConnection.GetSchema,只有 MetaDataCollections 类别是必需的。提供程序可以选择不提供任何或所有其他 4 个类别的信息。

其次,每个提供程序可以公开相同元数据集合的不同信息。例如,Tables 集合的结构完全取决于提供程序编写者。举个例子,SqlClient 提供程序在 Tables 集合中公开了 4 个信息项:table_catalog、table_schema、table_name 和 table_type。OracleClient 提供程序仅公开了 3 个信息项(OWNER、TABLE_NAME 和 TYPE),因为 oracle 数据库不包含多种目录。对每个提供程序来说限制和限制项的数量可以是不同的。再次以表的情况为例,SqlClient 提供程序支持 4 个限制,而 oracleClient 提供程序只支持 2 个。限制也不必按照任何指定的顺序发生。所以与在 OLE DB 和 ODBC API 中不同,这里没有委托管理的元数据结构、大量元数据或者元数据顺序。提供程序可以自由公开任何相关的元数据。但是,如果一个特定的应用程序(如 Visual Studio)要求在一个应用程序里使用的所有 .NET 数据提供程序中元数据是一致的,它也能够通过覆盖提供程序的标准行为来获得这个行为。我们将在后面的用户自定义小节进一步讨论这个问题。

提供程序编写者可以将元数据逻辑直接硬编码到他们的提供程序中,每个提供程序编写者为了获得相似的元数据可以使用不同的内部算法。例如,在实现 OLE DB 的 ISchemaRowset 方法时,这就是过去完成它的方法。但是,在 ADO.NET 2.0 中,在 System.Data.ProviderBase 命名空间中有一些基类是提供程序编写者可用的。4 个可用的 Microsoft 提供程序使用这些基类,因此它们都以相似的方法实现架构。我将用这个实现进行讲解,希望大多数编写提供程序的程序员喜欢 DataDirect 技术,而其他提供程序编写者也使用它。

公开元数据的基类是 DbMetaDataFactory。 实现它的一个子类的提供程序使用一个 XML 文件来定义其元数据提取行为。这些文件是在 System.Data.dll 和 System.Data.OracleClient.dll 中嵌入的资源,您可以通过从命令行运行 ILDASM.exe 来查看原始的 XML 文件。

>ildasm.exe System.Data.dll /out:dummy.il

查看从 ILDASM 生成的 XML 资源文件,如同剥开了洋葱的另一层。这个文件枚举了被支持的集合以及包含在每个元数据集合(通过架构)中的信息,并且看起来是使用 DataSet.WriteXml(XmlWriteMode.WriteSchema) 重载的 DataSet.WriteXml 方法的输出。最有趣的部分是在除了 DataSourceInformation 和 MetaDataCollections 元素中的 PopulationMechanism/PopulationString 子元素以外的所有元数据集合中的 MinimumVersion/MaximumVersion 元素。

使 用 MinimumVersion/MaximumVersion 允许提供程序编写者指定对于不同版本的数据库要执行哪些元数据查询。通过使用单个 MetaDataCollection 的多个元素,您可以使 GetSchema 对不同版本的数据库表现不同。举一个明显的例子,您可以使用与以前版本的 SQL Server 不同的 SQL Server 2005 各版本。这里是一个使用来自 SQL Server 元数据资源 (System.Data.SqlClient.SqlMetaData) 的 MinimumVersion 的例子:

清单 2. 数据类型集合中的数据类型 XML 的元数据项

<DataTypes>
<TypeName>xml</TypeName>
<ProviderDbType>25</ProviderDbType>
<ColumnSize>2147483647</ColumnSize>
<DataType>System.String</DataType>
<IsAutoIncrementable>false</IsAutoIncrementable>
<IsCaseSensitive>false</IsCaseSensitive>
<IsFixedLength>false</IsFixedLength>
<IsFixedPrecisionScale>false</IsFixedPrecisionScale>
<IsLong>true</IsLong>
<IsNullable>true</IsNullable>
<IsSearchable>true</IsSearchable>
<IsSearchableWithLike>false</IsSearchableWithLike>
<MinimumVersion>09.00.000.0</MinimumVersion>
<IsLiteralSupported>false</IsLiteralSupported>
</DataTypes>

这定义了关于 SQL Server 数据类型 XML 的信息。MinimumVersion 指示出,这个数据类型只在使用 SQL Server 2005 时可用。如果您要求 SqlConnection.GetSchema 提供数据库支持的数据类型列表,只有 SQL Server 2005 的各版本数据库(SQL Server 2005 是版本 9,当前的beta 2 版是 09.00.852.2)会报告它们支持 XML 数据类型。

对于通常被 INFORMATION_SCHEMA(如表、视图或存储过程)公开的集合,PopulationMechanism 和 PopulationString 是工作开始的地方。在这个实现中使用了三个 PopulationMechanisms:DataTableSQLCommandPrepareCollection。DataTable 用于填充元数据集合。使用 DataTable 意味着用于填充集合的信息是在 XML 资源文件本身当中。在每种情况下,PopulationString 是当 XML 资源文件加载到一个 .NET DataSet 时,生成的 DataTable 的名称。SQLCommand 意味着提供程序将使用一个 DbCommand 实例来发出对数据库的命令。如果您查看由 SQLCommand 产生的集合的一个 PopulationString:

清单 3. SQL Server 中的数据库(目录)项 — MetaDataCollection

<MetaDataCollections>
<CollectionName>Databases</CollectionName>
<NumberOfRestrictions>1</NumberOfRestrictions>
<NumberOfIdentifierParts>1</NumberOfIdentifierParts>
<PopulationMechanism>SQLCommand</PopulationMechanism>
<PopulationString>select name as database_name, dbid, crdate as create_date from master..sysdatabases where name = {0}</PopulationString>
</MetaDataCollections>

当限制在 DbConnection.GetSchema 中使用时,很容易就能够推断出字符串替换将被应用到“基查询”中。如果没有限制被指定,那么实际上该谓词将被剥离出查询。

当 PopulationMechanism 的值为 PrepareCommand 时,提供程序编写者可以使用自定义机制。有一个 DbMetaDataFactory 的 PrepareCommand 方法,如果它被提供程序编写者覆盖,就可以被编码来使用提供程序选择的任何自定义语义。这一机制被用在 SqlClient 中来生成 DataTypes 元数据集合。PrepareCommandSqlMetaDataFactory 子类实现首先从 DataTable 中读取由 SQL Server 支持的内置数据类型,如同用其他元数据集合一样;然后,如果数据库是 SQL Server 2005 的话,使用自定义逻辑来将用户定义的类型添加到集合中。(注:SQL Server 2005 可以将 .NET 类作为用户定义的类型公开。更多信息请参阅 A First Look at SQL Server 2005 for Developers 的第 5 章。)

用户自定义

除了提供程序自定义机制外,也有允许程序员在每个应用程序基础上自定义架构信息的挂钩!在加载嵌入资源之前,DbConnectionFactory CreateMetaDataFactory 将参考应用程序配置文件。每个提供程序都可以用任何它选择的方法实现 CreateMetaDataFactory 来为其 DbMetaDataFactory 获取 XML 流,但是那 4 个 Microsoft 提供程序遵循一个公共模式。每个 Microsoft 提供程序将查找一个按提供程序本身命名的应用程序配置设置(如 system.data.sqlclient)。在这个设置元素中您可以 添加或删除名值对。DbMetaDataFactory 查找一个名称“MetaDataXml”。与特殊名称对应的值是一个文件的名称。这是一个简单的文件名 — 这个文件必须存在于 .NET 安装位置的 CONFIG 子目录中。这是 machine.config 和安全配置设置所在的目录。这个文件必须包含整个的架构配置信息集,而不仅仅是那些更改。

出于多个原因,对于支持此机制的提供程序, 您可以使用这个机制。例如,您可以更改 oracleClient 提供程序中的架构查询来使用“USER”目录视图而不是“ALL”目录视图。因为“USER”视图不包含关于内部数据库表的信息,例如,表列表将会短很多 并且更易于使用。另一个示例可能包括为所有的 .NET 数据提供程序编码输出元数据 XML 文件,这提供给您一致的标准元数据集,该元数据集可能正好符合 SQL-99 INFORMATION_SCHEMA 视图。这可能恰恰适合您的应用程序。

一个更具体的例子是,如果我想要公开 SQL Server 2005 中关于 SQL Server Service Broker 的元数据集合的信息。这些集合可以包括 QUEUE、SERVICE、CONTRACT 和消息类型。我会从嵌入的 XML 资源文件开始并用我的新集合上的信息修饰它。如果这个文件的名称是 SQLBrokerAware.xml,我会安装这个文件,我的应用程序配置文件将为如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.data.sqlclient>
<settings>
<add name="MetaDataXml" value="SQLBrokerAware.xml">
</add>
</settings>
</system.data.sqlclient>
</configuration>

这就是所有的步骤。使用这个设置,我可以编写代码 — 在其中 Service Broker 元数据是可用于客户端的内置元数据的组成部分。对所有队列来说,代码可能如下所示:

using (SqlConnection conn = new SqlConnection(connstring))
{
conn.Open();
// this includes Service Broker metadata collections
Table t = conn.GetSchema(DbMetaDataCollectionNames.MetaDataCollections);
// get all the queues in my database
Table queues = conn.GetSchema("Queues");
}

真是非常酷!本文包含一个添加 Service Broker 元数据的代码示例。 尽管这是一个非常强大的功能,它还是有可能被滥用的。请记住您需要将元数据 XML 文件分发到每个使用它的应用程序,并说服系统管理员为您将其安装在 CONFIG 目录中。而且您需要用发布的提供程序的每个新版本来维护它。因为使用一般元数据 API 的理由之一是可拥有跨数据库和应用程序的一致元数据,所以这个功能不应被无故使用。还需注意此时您不能提供 PrepareCommand 的自定义实现。

关于自定义的最后要注意的,您可能已经猜到了,自定义和资源对于 OLE DB 和 ODBC 的桥提供程序的使用是不同的。当您使用这些提供程序时,默认的 Odbc 或 OleDb XML 资源文件被使用,然后您不仅可以自定义主要的 Odbc 或 OleDb 架构行为,而且可以在每个提供程序基础上自定义行为。如果您想要指定自己的提供程序或者驱动程序,在添加/删除设置子元素中使用的名称属性不能是 MetaDataXml,而应该是 [providershortname]:MetaDataXml。如果您想让您的文件成为 OleDb 或 Odbc 数据提供程序的默认文件,您甚至可以指定 defaultMetaDataXml 的名称。

小结:元数据支持的最终部分

在结束前,我只想说说其他两个不是通过 DbConnection.GetSchema 公开的元数据扩展。 DbCommandBuilder 包含两个属性,QuoteIdentifierUnquoteIdentifier,它们允许您在由 CommandBuilder 生成的命令中自定义标识符。举个例子,根据您的会话设置,在 SQL Server 中您可以使用双引号 (") 或括号('[' 和 ']')来引用标识符。最后,在 System.Data.Sql 命名空间中的 SqlMetaData 类被用于公开 SQL Server DataReader 中的元数据并允许您在 SqlCommand 使用的 Parameters 中 设置这个元数据。虽然不是任何地方在细节上都非常接近,但是这个元数据在概念上与在 DataTypes 元数据集合中公开的元数据相似。SqlMetaData 对 SqlClient 数据提供程序和 SQL Server 2005 包括的 in-database SQLServer 数据提供程序都是适用的。SqlMetaData 增大了当前通过 SqlDataReader.GetSchemaTable() 方法公开的行集合元数据。

此 时您很可能同意 ADO.NET 2.0 元数据基础结构是您所见过的最强大、灵活和可自定义的结构。它将 ADO.NET 发展成为一个完全面向对象的数据库 API。工具供应商、提供程序编写者和 Visual Studio 数据工具用户将会高兴地在街上跳舞 — 我们那里见。

Bob Beauchemin,DevelopMentor 的讲师、课程作者和数据库课程联络员。作为以数据为中心的分布式系统的架构师、程序员和管理员,他有超过 25 年的经验。他一直为 Microsoft Systems Journal 和 SQL Server Magazine 等杂志撰写 ADO.NET、OLE DB 和 SQL Server 方面的文章,并且是 A First Look at SQL Server 2005 for Developers Essential ADO.NET 的作者。

转到原英文页面

[代码]某人封装的一个ADO.net操作类

mikel阅读(646)

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.Remoting.Messaging;
using System.Data;
using System.Data.SQLClient;
using System.Configuration;
namespace LTP.SQLServerDAL
{
///

/// ADO.NET数据库操作基础类。
///

public abstract class DbManagerSQL
{
//数据库连接字符串
protected static string connectionString = ConfigurationSettings.AppSettings[“ConnectionString”];
public DbManagerSQL()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
///

/// 执行SQL语句,返回影响的记录数
///

/// ///
public static int ExecuteSql(string SQLString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(SQLString,connection))
{
try
{
connection.Open();
int rows=cmd.ExecuteNonQuery();
return rows;
}
catch(System.Data.SqlClient.SqlException E)
{
throw new Exception(E.Message);
}
}
}
}
///

/// 执行两条SQL语句,实现数据库事务。
///

/// /// public static void ExecuteSqlTran(string SQLString1,string SQLString2)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection=connection;
SqlTransaction tx=connection.BeginTransaction();
cmd.Transaction=tx;
try
{
cmd.CommandText=SQLString1;
cmd.ExecuteNonQuery();
cmd.CommandText=SQLString2;
cmd.ExecuteNonQuery();
tx.Commit();
}
catch(System.Data.SqlClient.SqlException E)
{
tx.Rollback();
throw new Exception(E.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
///

/// 执行多条SQL语句,实现数据库事务,每条语句以“;”分割。
///

/// public static void ExecuteSqlTran(string SQLStringList)
{
using (OdbcConnection conn = new OdbcConnection(connectionString))
{
conn.Open();
OdbcCommand cmd = new OdbcCommand();
cmd.Connection=conn;
OdbcTransaction tx=conn.BeginTransaction();
cmd.Transaction=tx;
try
{
string [] split= SQLStringList.Split(new Char [] { ';'});
foreach (string strsql in split)
{
if (strsql.Trim()!=””)
{
cmd.CommandText=strsql;
cmd.ExecuteNonQuery();
}
}
tx.Commit();
}
catch(System.Data.Odbc.OdbcException E)
{
tx.Rollback();
throw new Exception(E.Message);
}
}
}
///

/// 执行带一个存储过程参数的的SQL语句。
///

/// /// ///
public static int ExecuteSql(string SQLString,string content)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(SQLString,connection);
System.Data.SqlClient.SqlParameter myParameter = new System.Data.SqlClient.SqlParameter ( “@content”, SqlDbType.NText);
myParameter.Value = content ;
cmd.Parameters.Add(myParameter);
try
{
connection.Open();
int rows=cmd.ExecuteNonQuery();
return rows;
}
catch(System.Data.SqlClient.SqlException E)
{
throw new Exception(E.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
///

/// 向数据库里插入图像格式的字段
///

/// /// ///
public static int ExecuteSqlInsertImg(string strSQL,byte[] fs)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(strSQL,connection);
System.Data.SqlClient.SqlParameter myParameter = new System.Data.SqlClient.SqlParameter ( “@fs”, SqlDbType.Image);
myParameter.Value = fs ;
cmd.Parameters.Add(myParameter);
try
{
connection.Open();
int rows=cmd.ExecuteNonQuery();
return rows;
}
catch(System.Data.SqlClient.SqlException E)
{
throw new Exception(E.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
///

/// 执行一条计算查询结果语句,返回查询结果(整数)。
///

/// ///
public static int GetCount(string strSQL)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(strSQL,connection);
try
{
connection.Open();
SqlDataReader result = cmd.ExecuteReader();
int i=0;
while(result.Read())
{
i=result.GetInt32(0);
}
result.Close();
return i;
}
catch(System.Data.SqlClient.SqlException e)
{
throw new Exception(e.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
///

/// 执行一条计算查询结果语句,返回查询结果(object)。
///

/// ///
public static object GetSingle(string SQLString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(SQLString,connection);
try
{
connection.Open();
object obj = cmd.ExecuteScalar();
if((Object.Equals(obj,null))||(Object.Equals(obj,System.DBNull.Value)))
{
return null;
}
else
{
return obj;
}
}
catch(System.Data.SqlClient.SqlException e)
{
throw new Exception(e.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
///

/// 执行查询语句,返回SqlDataReader
///

/// ///
public static SqlDataReader ExecuteReader(string strSQL)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(strSQL,connection);
SqlDataReader myReader;
try
{
connection.Open();
myReader = cmd.ExecuteReader();
return myReader;
}
catch(System.Data.SqlClient.SqlException e)
{
throw new Exception(e.Message);
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
///

/// 执行查询语句,返回DataSet
///

/// ///
public static DataSet Query(string SQLString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet ds = new DataSet();
try
{
connection.Open();
SqlDataAdapter command = new SqlDataAdapter(SQLString,connection);
command.Fill(ds,”ds”);
}
catch(System.Data.SqlClient.SqlException ex)
{
throw new Exception(ex.Message);
}
return ds;
}
}
#region 存储过程操作
///

/// 运行存储过程
///

/// /// ///
public static SqlDataReader RunProcedure(string storedProcName, IDataParameter[] parameters )
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataReader returnReader;
connection.Open();
SqlCommand command = BuildQueryCommand( connection,storedProcName, parameters );
command.CommandType = CommandType.StoredProcedure;
returnReader = command.ExecuteReader();
//Connection.Close();
return returnReader;
}
}
private static SqlCommand BuildQueryCommand(SqlConnection connection,string storedProcName, IDataParameter[] parameters)
{
SqlCommand command = new SqlCommand( storedProcName, connection );
command.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add( parameter );
}
return command;
}
public static DataSet RunProcedure(string storedProcName, IDataParameter[] parameters, string tableName )
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet dataSet = new DataSet();
connection.Open();
SqlDataAdapter sqlDA = new SqlDataAdapter();
sqlDA.SelectCommand = BuildQueryCommand(connection, storedProcName, parameters );
sqlDA.Fill( dataSet, tableName );
connection.Close();
return dataSet;
}
}
#endregion
}
}

[教程]CSS区别不同浏览器写法

mikel阅读(750)

区别不同浏览器,CSS hack写法:
区别IE6与FF:
#demo{
background:orange;
*background:blue;
}
区别IE6与IE7:
#demo{
background:green !important;
background:blue;
}
区别IE7与FF:
#demo{
background:orange;
*background:green;
}
区别FF,IE7,IE6:
#demo{
background:orange;
*background:green !important;
*background:blue;
}
注:IE都能识别*;标准浏览器(如FF)不能识别*;
IE6能识别*,但不能识别 !important,
IE7能识别*,也能识别!important;
FF不能识别*,但能识别!important;
我自己是使用下划线,我最开始区别 ie6 和 FF 的时候 习惯在代码里面加 /**/如: margin-top:1px;
margin-top/**/:5px;去实现我现在改变了写法
#demo{
background:orange;
_background:green !important;
_background:blue;
}
理由和上面说的一样,FF不认_ ie认_ ie6不认识!important 根据这些区别,采用不同的Hack 手法