C# 如果数据库中的列发生更改,是否有方法不中断代码?

C# 如果数据库中的列发生更改,是否有方法不中断代码?,c#,C#,假设我已经声明了一个datatable,并且为此datatable分配了一个调用存储过程返回的结果,那么现在,我的datatable在从中访问行时包含如下内容: string name = dr["firstname"]; int age = (int)dr["age"]; 如果firstname更改为first_name,并且删除了age,代码显然会中断,因为现在模式已中断,那么有没有一种方法可以始终自动保持模式与代码同步,而无需手动执行?是否存在某种元描述文件来描述数据库表中的列并相应地更

假设我已经声明了一个datatable,并且为此datatable分配了一个调用存储过程返回的结果,那么现在,我的datatable在从中访问行时包含如下内容:

string name = dr["firstname"];
int age = (int)dr["age"];

如果firstname更改为first_name,并且删除了age,代码显然会中断,因为现在模式已中断,那么有没有一种方法可以始终自动保持模式与代码同步,而无需手动执行?是否存在某种元描述文件来描述数据库表中的列并相应地更新它们?在这种情况下,LINQ是否会因为其强类型的特性而有所帮助?

防止这种情况的唯一方法是使用存储过程,选择列并将其重命名为标准名称,然后返回到应用程序中。但是,这确实为数据库增加了另一层维护。

这就是创建NHibernate等ORM解决方案的原因


或者是基于数据库架构的代码生成器。

为什么不想更改代码?如果删除了年龄,为什么还要在代码中尝试抓住它

Linq所做的是尝试将所有业务逻辑保存在一个位置(源代码)中,而不是在数据库和源代码之间拆分


删除数据列时,应更改代码。

是的,对所有访问使用存储过程,并在表中为输出到客户端代码的实际属性名别名。。。然后,如果表中的实际列名发生更改,您只需更改存储过程中的sql,并保持别名不变,并且客户端代码可以保持不变,删除“age”时不会有帮助,但如果您知道列将始终以相同的顺序返回,即使名称发生更改,然后您可以通过列名引用它们,例如:

string name = dr[0];
int age = (int)dr[1];
根据您的DB版本,您还可以签出数据访问生成器,例如

  • 好的老式视图是按列名选择的,它们总是按指定的顺序输出具有指定名称的列。如果下面的表需要更改,则视图会在必要时进行修改,但输出仍与基础表更改之前相同,就像对象的接口一样。应用程序引用视图而不是表,并继续正常工作。这可以归结为标准的数据库应用程序设计,应该在任何(甚至是基础的)数据架构师课程中教授,但我很少看到这些在业务应用程序中实际使用。事实上,我目前正在进行的项目是我第一次看到这种方法的应用,看到它被正确地使用真是令人耳目一新

  • 使用存储过程,如果表发生更改,请修改存储过程,使输出保持不变—以类似的方式使用,将应用程序与基础表隔离,从而使应用程序与任何表更改隔离。如果您希望在视图更合适的地方进行动态连接、筛选和聚合,那么这还不够

  • 如果要在应用程序端执行此操作,请在查询中直接指定要查询的字段的名称,而不是使用“select*”并依赖字段名称来存在。但是,如果表上的字段名发生更改,或者某个列被删除,您仍然会被卡住,您必须修改查询

  • 如果字段名称将更改,但所有字段将始终存在,这些字段的内容将保持不变,并且字段的顺序将保持不变,则可以按索引而不是按名称引用字段

  • 正如其他人所指定的那样使用对象关系映射器,但我认为这并不一定能教给我们好的设计,而是希望框架的设计足够好,适合您所做的事情,这可能是事实,也可能不是事实。但我并不认为这是一个好方法


  • 显然,您必须在数据库和应用程序之间引入另一层抽象。是的,该层可以是Linq2Sql、实体框架、NHibernate或任何其他ORM(对象关系映射)框架。

    现在关于“自动”的问题。。。也许这种小变化(重命名列)可以由一些工具/框架自动处理。但我认为任何框架都不能保证自动正确处理更改。在许多情况下,您必须手动在数据库和新层之间进行“映射”,这样您就可以使应用程序的其余部分不受影响。

    从给出的所有答案中可以看出,您所寻找的并不存在。这样做的原因是您应该记住,程序本质上是数据处理例程,因此在不更改程序中其他内容的情况下,无法更改数据。如果不是列的名称,而是正在更改的类型,该怎么办?或者,如果删除该列,会发生什么情况

    总而言之,这些问题没有好的解决办法。数据是应用程序不可分割的一部分——如果数据发生变化,至少需要做一些工作。但是,如果您希望名称发生更改(例如,数据库不是您的,并且所有者已通知您其名称将来可能会更改),并且您不希望因此而重新部署应用程序,那么除了重新编译源代码之外的其他备选方案(如其他答案中所述)包括:

    • 使用存储过程
      • 您可以使用存储过程向应用程序提供数据。对于建议的更改(重命名列),负责数据库模式的DBA或管理员也应该更改存储过程
      • 优点:由于数据库中的微小更改,不需要重新编译
      • 缺点:更多的人工制品
        string name = dr["firstname"];
        int age = (int)dr["age"];
        
        private const string CUSTOMER_COLUMN_FIRST_NAME = "firstname"
        private const string CUSTOMER_COLUMN_AGE = "AGE"
        
        string name = dr[CUSTOMER_COLUMN_FIRST_NAME];
        int age = (int)dr[CUSTOMER_COLUMN_AGE];