在Crystal Reports中打印票证,SQL查询优化,c#

时间:2016-05-29 05:15:12

标签: c# sql dataset sqlconnection datarow

我正在使用水晶报告根据DB中的唯一ID生成一些故障单。但是,我现在面临的挑战是在要打印的水晶报告中每英亩产生2张票。

下面我有代码应该发送查询并填充水晶报表查看器。超过9000个独特的记录和超过74000英亩的土地,这是行不通的。任何人都可以帮助或帮助更好的方法来做到这一点。

此代码运行sql server 2008 r2内存不足:

private void button1_Click(object sender, EventArgs e)
{
    try{
        SqlConnection con = new SqlConnection("Data Source=localhost\\DEV;Initial Catalog=db;Integrated Security=True");
        var f_id = textBox2.Text;  //Unique ID Not used to generate all tickets
        var n_copies = textBox1.Text; //Number of copies default 1
        var t_per_acre = textBox3.Text; //Set default at 2 Tickets per acre
        string sql = "Select * From dbo.CParcel";
        SqlDataAdapter sda = new SqlDataAdapter(sql, con);
        DataSet ds = new DataSet();
        sda.Fill(ds, "CParcel");
        foreach (DataRow theRow in ds.Tables["CParcel"].Rows)
        {
            decimal get_acreage = System.Convert.ToDecimal(theRow["ACREAGE"]);
            int acr = (int)(get_acreage + 0.5m);
            int t_t_per_acr = acr * System.Convert.ToInt32(t_per_acre);
            int t_t_per_acr_per_copy = t_t_per_acr * System.Convert.ToInt32(n_copies);
            for (int i = 1; i < t_t_per_acr_per_copy; i++)
            {
                sql = sql + " Union All SELECT * FROM dbo.CParcel";
            }
        }
        SqlDataAdapter tsda = new SqlDataAdapter(sql, con);
        DataSet ds2 = new DataSet();
        tsda.Fill(ds2, "CParcel");
        crystal.SetDataSource(ds2);
        crystal.SetDatabaseLogon("sa", "password");
        crystalReportViewer1.ReportSource = crystal;

    }
    catch (Exception ex)
    {
        // Print error message
        MessageBox.Show(ex.Message);
    }
}

1 个答案:

答案 0 :(得分:1)

考虑以下修改,这是非常小的,只是尝试收集一些计数器。

private void button1_Click(object sender, EventArgs e)
{
    int i_xyz = 0, j_xyz = 0;   // Drew added
    try
    {
        SqlConnection con = new SqlConnection("Data Source=localhost\\DEV;Initial Catalog=db;Integrated Security=True");
        var f_id = textBox2.Text;  //Unique ID Not used to generate all tickets
        var n_copies = textBox1.Text; //Number of copies default 1
        var t_per_acre = textBox3.Text; //Set default at 2 Tickets per acre
        string sql = "Select * From dbo.CParcel";   // STARTING POINT A
        SqlDataAdapter sda = new SqlDataAdapter(sql, con);
        DataSet ds = new DataSet();
        sda.Fill(ds, "CParcel");
        foreach (DataRow theRow in ds.Tables["CParcel"].Rows)
        {
            i_xyz++;    // Drew added
            decimal get_acreage = System.Convert.ToDecimal(theRow["ACREAGE"]);
            int acr = (int)(get_acreage + 0.5m);
            int t_t_per_acr = acr * System.Convert.ToInt32(t_per_acre);
            int t_t_per_acr_per_copy = t_t_per_acr * System.Convert.ToInt32(n_copies);
            for (int i = 1; i < t_t_per_acr_per_copy; i++)
            {
                j_xyz++;    // Drew added
                sql = sql + " Union All SELECT * FROM dbo.CParcel";
            }
        }
        // POINT B <------------------

        // STOP !!
        // RIGHT HERE what is the value of i_xyz and j_xyz ?? In particular j_xyz
        // also flush sql out to a text file and get a good look at it

        //SqlDataAdapter tsda = new SqlDataAdapter(sql, con);
        //DataSet ds2 = new DataSet();
        //tsda.Fill(ds2, "CParcel");
        //crystal.SetDataSource(ds2);
        //crystal.SetDatabaseLogon("sa", "password");
        //crystalReportViewer1.ReportSource = crystal;

    }
    catch (Exception ex)
    {
        // Print error message
        MessageBox.Show(ex.Message);
    }
}

POINT B之后,你会j_xyz知道你在sql字符串上添加UNION ALL的次数。我能理解你的联盟是否添加了一些其他有意义(和不同)数据子集的粒度,比如here(尽管是一个不同的数据库引擎)。但是想想一个联盟在不同数据这样的事情上很有用,而且如果没有联合就很难实现它。

但是在你的情况下,你每次只使用相同的数据进行union all select *。并且可能在此过程中创建一个巨大的sql语句来执行此操作。那个j_xyz变量会告诉你你加上它的次数。

其他想法包括不要指定select *,而只是指定报告所需的列。并且还遵循内存管理的最佳实践,使用Dispose,设置为null,或者当Adam使用&#34;使用资源时显示here时将执行的操作。&#34; Using

因此,总而言之,使用串联的sql字符串,毫无疑问例程会失败。