Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.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 partial方法时发生SQL Server超时异常_C#_.net_Linq To Sql_Datacontext - Fatal编程技术网

C# 扩展Linq partial方法时发生SQL Server超时异常

C# 扩展Linq partial方法时发生SQL Server超时异常,c#,.net,linq-to-sql,datacontext,C#,.net,Linq To Sql,Datacontext,在.NET4.0和LINQtoSQL中,我试图使用分部类从更新方法(现有的DBML方法)中“触发”更改。为简单起见,设想一个包含列Id和列值的表Things auto gen DBML包含一个方法OnValueChanged,我将扩展该方法,作为练习,尝试更改另一行中的一个值: public partial class Things { partial void OnValueChanged() { MyAppDataCont

在.NET4.0和LINQtoSQL中,我试图使用分部类从更新方法(现有的DBML方法)中“触发”更改。为简单起见,设想一个包含列Id和列值的表Things

auto gen DBML包含一个方法OnValueChanged,我将扩展该方法,作为练习,尝试更改另一行中的一个值:

   public partial class Things
    {
        partial void OnValueChanged()
        {
            MyAppDataContext dc = new MyAppDataContext();
            var q = from o in dc.GetTable<Things>() where o.Id == 13 select o;
            foreach (Things o in q)
            {
                o.Value = "1";  // try to change some other row
            }
            try
            {
                dc.SubmitChanges();
            }
            catch (Exception)
            {
                // SQL timeout occurs 
            }
        }
    }
公共部分类事物
{
部分无效OnValueChanged()
{
MyAppDataContext dc=新的MyAppDataContext();
var q=从dc.GetTable()中的o开始,其中o.Id==13选择o;
foreach(事物在q中为o)
{
o、 Value=“1”//尝试更改其他行
}
尝试
{
dc.提交更改();
}
捕获(例外)
{
//发生SQL超时
}
}
}
发生SQL超时错误。我怀疑datacontext在当前OnValueChanged()方法处理其datacontext之前尝试提交更改()时会感到困惑,但我不确定

在现有的DBML生成方法中,我通常找不到一个触发DB更新的好模式示例

有没有人能提供一些建议,说明为什么这样做不起作用,以及我如何才能完成一些可行的事情?(我知道我可以在SQL数据库中触发,但我不想采用这种方式。)


谢谢

首先,您根本没有在函数中处理
DataContext
。使用语句将其包装在

实际的问题来自这样一个事实:您正在通过对检索到的值设置
Value
属性来递归调用自己。在点击
StackOverflowException
之前,您刚刚进入超时

不清楚你想在这里做什么;如果您试图在此处设置
属性时与在其他任何地方设置属性时允许不同的行为,那么使用标志就足够简单了。在分部类中,在更新值之前,在
foreach
块中的每个项目上声明名为
updateingvalue
internal
实例布尔自动属性,并将其设置为
true
,然后在更新值之后将其设置为
false
。然后,作为
OnValueChanged
中的第一行,检查以确保
updateingvalue
false

像这样:

public partial class Things
{
     internal bool UpdatingValue { get; set; }

     partial void OnValueChanged()
     {
         if (UpdatingValue) return;

         using(MyAppDataContext dc = new MyAppDataContext())
         {
             var q = from o in dc.GetTable<Things>() where o.Id == 13 select o;
             foreach (Things o in q)
             {
                 o.UpdatingValue = true;
                 o.Value = "1";  // try to change some other row
                 o.UpdatingValue = false;
             }

             dc.SubmitChanges();
         }
     }
 }
公共部分类事物
{
内部布尔更新值{get;set;}
部分无效OnValueChanged()
{
if(updatevalue)返回;
使用(MyAppDataContext dc=new MyAppDataContext())
{
var q=从dc.GetTable()中的o开始,其中o.Id==13选择o;
foreach(事物在q中为o)
{
o、 更新值=真;
o、 Value=“1”//尝试更改其他行
o、 updatevalue=false;
}
dc.提交更改();
}
}
}

我怀疑您可能通过更改事物的OnValueChanged事件处理程序中事物的值引入了无限递归


对我来说,解决问题的更简洁的方法不是在DBML文件中生成类,而是在创建的类上使用。通过这样做,您可以在属性/列的设置器中进行“触发器”修改。

我也遇到了类似的问题。我不认为这是代码中的错误,我倾向于SqlDependency如何工作的错误。我做了和你一样的事情,但是我逐步地测试了它。如果select语句返回1-100行,那么它工作正常。如果select语句返回1000行,那么我将得到SqlException(超时)

这不是堆栈溢出问题(至少在这个客户机代码中不是)。在OnValueChanged事件处理程序处放置断点表明,当SubmitChanges调用挂起时,不会再次调用它

在调用SubmitChanges之前,可能需要OnValueChanged调用必须返回。也许在不同的线程上调用SubmitChanges可能会有所帮助

我的解决方案是将代码包装在一个大的try/catch块中,以捕获SqlException。如果发生这种情况,则执行相同的查询,但不使用SqlDependency,也不将其附加到命令。这不再挂起SubmitChanges调用。紧接着,我重新创建SqlDependency,然后再次进行查询,以重新注册依赖关系

这并不理想,但至少它最终会处理所有行。只有当要选择的行很多时,才会出现问题,并且如果程序运行顺利,这不应该发生,因为它一直在追赶

    public Constructor(string connString, CogTrkDBLog logWriter0)
    {
        connectionString = connString;
        logWriter = logWriter0;

        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand("SELECT is_broker_enabled FROM sys.databases WHERE name = 'cogtrk'", conn))
            {
                bool r = (bool) cmd.ExecuteScalar();
                if (!r)
                {
                    throw new Exception("is_broker_enabled was false");
                }
            }
        }
        if (!CanRequestNotifications())
        {
            throw new Exception("Not enough permission to run");
        }


        // Remove any existing dependency connection, then create a new one.
        SqlDependency.Stop(connectionString);
        SqlDependency.Start(connectionString);

        if (connection == null)
        {
            connection = new SqlConnection(connectionString);
            connection.Open();
        }

        if (command == null)
        {
            command = new SqlCommand(GetSQL(), connection);
        }

        GetData(false);
        GetData(true);
    }


    private string GetSQL()
    {
        return "SELECT id, command, state, value " +
        " FROM dbo.commandqueue WHERE state = 0 ORDER BY id";

    }
    void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    {
        // Remove the handler, since it is only good
        // for a single notification.
        SqlDependency dependency = (SqlDependency)sender;
        dependency.OnChange -= dependency_OnChange;

        GetData(true);
    }

    void GetData(bool withDependency)
    {
        lock (this)
        {
            bool repeat = false;
            do {
                repeat = false;
                try
                {
                    GetDataRetry(withDependency);
                }
                catch (SqlException)
                {
                    if (withDependency) {
                        GetDataRetry(false);
                        repeat = true;
                    }
                }
            } while (repeat);
        }
    }

    private void GetDataRetry(bool withDependency)
    {
        // Make sure the command object does not already have
        // a notification object associated with it.
        command.Notification = null;

        // Create and bind the SqlDependency object
        // to the command object.

        if (withDependency)
        {
            SqlDependency dependency = new SqlDependency(command);
            dependency.OnChange += dependency_OnChange;
        }


        Console.WriteLine("Getting a batch of commands");
        // Execute the command.
        using (SqlDataReader reader = command.ExecuteReader())
        {
            using (CommandQueueDb db = new CommandQueueDb(connectionString))
            {
                foreach (CommandEntry c in db.Translate<CommandEntry>(reader))
                {
                    Console.WriteLine("id:" + c.id);
                    c.state = 1;
                    db.SubmitChanges();
                }
            }
        }
    }
public构造函数(string connString,CogTrkDBLog logWriter0)
{
connectionString=connString;
logWriter=logWriter0;
使用(SqlConnection conn=newsqlconnection(connString))
{
conn.Open();
使用(SqlCommand cmd=newsqlcommand(“SELECT是从sys.databases启用的,其中name='cogtrk',conn))
{
bool r=(bool)cmd.ExecuteScalar();
if(!r)
{
抛出新异常(“is_broker_enabled was false”);
}
}
}
如果(!CanRequestNotifications())
{
抛出新异常(“没有足够的运行权限”);
}
//删除任何现有的依赖关系连接,然后创建一个新的依赖关系连接。
SqlDependency.Stop(connectionString);
SqlDependency.Start(connectionString);
if(连接==null)
{
连接=新的SqlConnection(connectionString);
connection.Open();
}
如果(命令==null)
{
通用域名格式