Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 没有数据库的Linq到SQL引用完整性_C#_Sql Server 2008_Linq To Sql - Fatal编程技术网

C# 没有数据库的Linq到SQL引用完整性

C# 没有数据库的Linq到SQL引用完整性,c#,sql-server-2008,linq-to-sql,C#,Sql Server 2008,Linq To Sql,我正在编写一个使用现有数据库的应用程序,该数据库有一些表,我根本无法修改,但我可以添加新表。 所以,假设我有一个旧表Cities,我可以读取、创建、更新和删除它,但是我不能修改模式。 然后,我添加了一个新表Clients,它有一个指向Cities的外键,但我无法在数据库服务器(SQLServer2008)上添加关系,因为它还修改Cities表,添加了一个关系。 所以我想,如果我将它们都添加到我的linq-to-sql上下文中,并在那里添加关系,那么linq-to-sql将足够聪明,可以为我检查引

我正在编写一个使用现有数据库的应用程序,该数据库有一些表,我根本无法修改,但我可以添加新表。 所以,假设我有一个旧表Cities,我可以读取、创建、更新和删除它,但是我不能修改模式。 然后,我添加了一个新表Clients,它有一个指向Cities的外键,但我无法在数据库服务器(SQLServer2008)上添加关系,因为它还修改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

你知道有没有可能强制引用完整性?或者在数据库上添加关系是唯一的方法?

您可以覆盖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交谈以进行所需的更改?您可以(我猜您也可以)添加一个表,但不能添加外键,所以数据库可能包含无效数据

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

或者这绝对是一个黑客行为:
  • 为自己编写数据库模式脚本
  • 在您的计算机上或您想在任何地方重新创建数据库
  • 添加新表,并向数据库添加外键
  • 从本地修改的数据库生成linq模式
  • 将连接字符串更改为真实字符串
而且非常脆弱:如果原始数据库中有任何更改,您必须在“虚拟”数据库中更改它


因此,尽管如此,还是要试着与你的老板、DBA或做出这一决定的人讲道理,因为你不能阻止被引用表中的其他人进行删除。

如果你可以添加新表,你也可以添加触发器。这是一种管理引用完整性的糟糕方法,但它会起作用……我可以补充。也许这是一个解决办法。。。我需要强制这些错误,因为我继承了系统,现在我需要维护它,但它几乎不检查引用完整性,并允许用户删除任何她想要的。。。我只是想确保它不会破坏数据库的完整性。@RaphaëlAlthaus您需要在引用的表Cities上设置一个触发器,以检查删除该城市后是否不存在任何客户端。他的前提是他不能修改城市模式。你需要“维护系统”,所以你可以修改它,但你不能修改数据库?这是否意味着数据库不“属于”系统?换句话说,其他系统也在修改数据?在这种情况下,在客户端执行的任何操作都不会阻止其他系统更改数据(例如,删除城市)。如果您拥有系统,包括数据库,请添加外键关系。@KrisVandermotten您是对的。我想。。。但这并不清楚:指向另一个模式的FK如何“改变”该模式?这可能会导致指向此模式的其他应用程序发生更改(“为什么我不能删除该城市”),当然,但与DB无关,不是吗?如果权利是确定的…问题是,旧数据库是另一个5年的超级测试数据库,仍然在开发巨大的visual basic 6程序。我正在为该程序编写一个扩展,它是根据客户的需要定制的。@gosukiwi没有真正的外键,您只能验证自己的更改,但如果其他应用程序中有人删除某个城市,您的数据就会被破坏,其他用户甚至不会注意到它。你就是无能为力。@gosukiwi那又怎样?VB6怪物是否需要删除城市,从而破坏您的代码?事实上,如果它仍在开发中,请与那些开发人员交谈,向他们解释删除城市的代码必须准备好接收数据库中的错误。哦,当你与他们交谈时,请提及VB6已经多年没有被微软支持作为开发平台了……我在这里有点陌生,他们知道,但这是当时使用的,我想它可能已经超过5年了,OOP是如此的新,我想当它开始的时候,他们没有费心使用它,而且它是公司最成功的程序之一。不过,有一个计划是使用ASP.NETMVC进行云计算。我想我必须手动检查,希望有最好的、非常好的测试人员。