【问题标题】:Linq to SQL Referential Integrity without database没有数据库的 Linq to SQL 参照完整性
【发布时间】:2012-06-13 04:42:35
【问题描述】:

我正在编写一个使用现有数据库的应用程序,该数据库有一些表我根本无法修改,但我仍然可以添加新表。 因此,假设我有一个旧表 Cities,我可以对其进行读取、创建、更新和删除,但我无法修改架构。 然后,我添加了一个新表 Clients,它具有 Cities 的外键,但我无法在数据库服务器 (SQL SERVER 2008) 上添加关系,因为它还修改了 Cities 表,添加了关系。 所以我想也许如果我将它们都添加到我的 linq-to-sql 上下文中,并在那里添加关系,linq-to-sql 会足够聪明地为我检查引用完整性,即使关系没有建立在数据库,它在上下文中。

我创建了一个新项目来尝试一下,我添加了两个没有关系的简单表,然后在 linq-to-sql 设计器上添加了关系,并尝试强制引用完整性异常,但看起来不是工作。

DBContextDataContext db = new DBContextDataContext();

City l = new City();
l.name= "Buenos Aires";
db.Cities.InsertOnSubmit(l);

Client c = new Client();
c.name = "Mike";
c.City = l;
db.Clients.InsertOnSubmit(c);

db.SubmitChanges(); // This works

db.Cities.DeleteOnSubmit(l); 
db.SubmitChanges(); // This shouldn't work, but it works

知道是否可以强制参照完整性?还是在数据库上添加关系是唯一的方法?

【问题讨论】:

  • 如果可以添加新表,也可以添加触发器。这是一种管理参照完整性的糟糕方法,但它会起作用......
  • 我可以添加。也许这是一个解决方案......我需要强制这些错误,因为我继承了系统,现在我需要维护它,但它几乎不检查参照完整性,并允许用户删除她想要的任何东西......我只是想确保它不会破坏数据库的完整性。
  • @RaphaëlAlthaus 您需要在引用的表 Cities 上使用触发器,以检查删除该城市后是否存在客户端。他的前提是他不能修改 Cities 模式。
  • 你需要“维护系统”,所以可以修改,但是不能修改数据库?这是否意味着数据库不“属于”系统?也就是说,其他系统也在修改数据?在这种情况下,您在客户端上所做的任何事情都不会阻止其他系统更改数据(例如删除城市)。如果您拥有系统,包括数据库,请添加外键关系。
  • @KrisVandermotten 你是对的。我认为......但这并不是那么清楚:指向另一个模式的 FK 将如何“改变”该模式?它可能会导致指向此架构的其他应用程序发生更改(“为什么我不能删除那个城市”),当然,但与 DB 无关,不是吗?如果权利没问题...

标签: c# sql-server-2008 linq-to-sql


【解决方案1】:

您可以覆盖 DataContex 上的 SubmitChanges 方法,并验证所做的更改。

    public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
    {
        bool everythingIsOK = true;

        var changes = GetChangeSet();
        var inserts = changes.Inserts;
        var deletes = changes.Deletes;
        var updates = changes.Updates;

        //verify everything is valid
        //...

        //if you need to, you can get the original state of the updated objects like this:
        foreach(object x in updates) {
            var original = this.GetTable(x.GetType()).GetOriginalEntityState(x);
            //verify the change doesn't break anything
            //...
        }

        if(everythingIsOK){ base.SubmitChanges(failureMode); }
    }

但是感觉很痛苦。您确定不能与 DBA 交谈以进行所需的更改吗?您可以(我猜您也可以)添加表,但不能添加外键,所以数据库可能包含无效数据?

此外,如果您必须以这种方式验证更改,这意味着您必须对数据库进行更多查询以验证所有密钥等是否有效。

或者这绝对是一个 hack:

  • 为自己编写 db 架构脚本
  • 在您的机器上或任何您想要的地方重新创建数据库
  • 添加新表,并将外键添加到数据库
  • 从本地修改的数据库生成 linq 架构
  • 把连接字符串改成真实的

而且非常脆弱:如果原始数据库发生任何变化,您必须在“虚拟”数据库中进行更改...

尽管如此,请尝试与您的老板、DBA 或做出此决定的人进行推理,因为您无法阻止其他人在引用的表中删除。

【讨论】:

  • 问题是旧数据库是另一个5年超级测试并且仍在开发HUGE visual basic 6程序的数据库。我正在为该程序编写一个扩展,这是根据客户的需求定制的。
  • @gosukiwi 没有真正的外键,您只能验证自己的更改,但是如果其他应用程序中的某人删除了一个城市,您的数据就会损坏,其他用户甚至都不会注意到。你对此无能为力。
  • @gosukiwi 那又怎样? VB6怪物是否要求可以删除城市,从而破坏您的代码?事实上,如果它仍在开发中,请与这些开发人员交谈并向他们解释,删除城市的代码必须准备好接收来自数据库的错误。
  • 哦,当您与他们交谈时,请提及微软多年来一直不支持 VB6 作为开发平台...
  • 我是新来的,他们知道,但这是当时使用的,我认为它可能甚至超过 5 年,OOP 太新了,他们没有打扰我想在它刚开始的时候使用它,这是公司最成功的项目之一。不过,有一个使用 ASP.NET MVC 的云计划。我想我必须手动检查,并希望有最好的、非常好的测试人员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多