C# 以编程方式将列添加到SQL Server数据库

C# 以编程方式将列添加到SQL Server数据库,c#,asp.net,sql,sql-server,tsql,C#,Asp.net,Sql,Sql Server,Tsql,我接管了一个需要重新编写的ASP.NET应用程序。我需要复制的这个应用程序的核心功能修改了通过ODBC从第三方软件访问的SQL Server数据库 第三方应用程序创建表示用户生成的打印机标签的文件。这些标签文件直接引用ODBC源的字段。表的每一行表示填充标签字段的产品。(因此,在这些文件中直接引用了表的列名。) ASP.NET应用程序允许用户通过添加或编辑表示产品的特定行,为标签引用的这些字段创建/更新数据 它还允许偶尔添加新字段。。。它实际上在核心表中创建了一个由标签引用的新列 我担心的是:我

我接管了一个需要重新编写的ASP.NET应用程序。我需要复制的这个应用程序的核心功能修改了通过ODBC从第三方软件访问的SQL Server数据库

第三方应用程序创建表示用户生成的打印机标签的文件。这些标签文件直接引用ODBC源的字段。表的每一行表示填充标签字段的产品。(因此,在这些文件中直接引用了表的列名。)

ASP.NET应用程序允许用户通过添加或编辑表示产品的特定行,为标签引用的这些字段创建/更新数据

它还允许偶尔添加新字段。。。它实际上在核心表中创建了一个由标签引用的新列


我担心的是:我以前从未以编程方式更改过现有表的列。现有应用程序似乎可以很好地处理此功能,但在我盲目地在新应用程序中执行相同的操作之前,我想知道在执行此操作时存在哪些陷阱(如果有)。。。如果有任何明显的替代方法。

当向表中添加太多列时,可能会出现问题,如果考虑性能,则必须小心(覆盖索引不适用,因此可能会执行昂贵的书签查找)


另一种选择是键-值对结构:,但这也有它的缺陷,最好按照您的建议创建新列。(KVP适用于设置)

一个风险是表格太宽。我曾经维护过一个可怕的应用程序,当新值添加到某个XML中时,它会“自动”添加3列(出于某种原因,它认为所有内容都是字符串、日期或数字,因此创建了3列)


还有其他一些技术,如序列化BLOB或以不同的方式设计表,可能会有所帮助。

我认为有一种选择是使用KVP表来存储动态“列”(如Mitch首先提到的),基于产品id将products表与KVP表连接,然后透视结果,以便在resultset中包含所有动态列


编辑:大致如下:

准备:

create table Product(ProductID nvarchar(50))

insert Product values('Product1')
insert Product values('Product2')
insert Product values('Product3')

create table ProductKVP(ProductID nvarchar(50), [Key] nvarchar(50), [Value] nvarchar(255))

insert ProductKVP values('Product1', 'Key2', 'Value12')
insert ProductKVP values('Product2', 'Key1', 'Value21')
insert ProductKVP values('Product2', 'Key2', 'Value22')
insert ProductKVP values('Product2', 'Key3', 'Value23')
insert ProductKVP values('Product3', 'Key4', 'Value34')
检索:

declare @forClause nvarchar(max),
        @sql nvarchar(max)

select @forClause = isnull(@forClause + ',', '') + '[' + [Key] + ']' from (
    select distinct [Key] from ProductKVP /* WHERE CLAUSE */
) t

set @forClause = 'for [Key] in (' + @forClause + ')'

set @sql = '
select * from (
select 
    ProductID, [Key], [Value]
from (
        select k.* from 
        Product p
        inner join ProductKVP k on (p.ProductID = k.ProductID)
        /* WHERE CLAUSE */
    ) sq
) t pivot (
    max([Value])' +
    @forClause + '
) pvt'

exec(@sql)
结果:

ProductID   Key1      Key2      Key3      Key4
----------- --------- --------- --------- -------
Product1    NULL      Value12   NULL      NULL
Product2    Value21   Value22   Value23   NULL
Product3    NULL      NULL      NULL      Value34

这在很大程度上取决于要对这些表运行的查询。KVP的主要缺点是更复杂的查询可能变得非常低效

两者的“混合”方法可能很有趣

将要查询的值存储在专用列中,将其余的保留在XML blob中(MS SQL具有很好的特性,甚至可以在XML中查询),或者也可以将其保存在KVP包中。就我个人而言,我真的不喜欢DBs中的KVP,因为您无法再构建特定于应用程序逻辑的索引

另一种方法是根本不建模特定列。您可以创建通用的“自定义属性”表,如:Attribute1、Attribute2、Attribute3、Attribute4(用于所需的数据类型等)。然后,您可以将元数据添加到数据库中,以描述AttrX对于特定类型的打印机标签的含义


同样,这实际上取决于您最终希望如何使用这些数据。

Yeap-这里有一篇关于KV对的文章-