Anonymous type and 'if' statements

P

Paolo

Is there any way I can avoid the ugly and repetitive 'if' construct shown
below?

I can't refactor into a separate method because qryTrans is an anonymous type.

I don't think I can use a switch statement either.

It works fine but is not aesthetically pleasing!

private void btnSearch_Click(object sender, EventArgs e)
{
qryStart = dtmpickStart.Value;
qryEnd = dtmpickEnd.Value;

var qryTrans =
from trans in dataSet.Transaction // get data for all
transactions
where ((trans.T_Date >= qryStart) // between start and end
dates
&& (trans.T_Date <= qryEnd))
select new
{
trans.T_Date,
trans.T_PayeeId,
trans.T_Category,
trans.T_SubCategory,
trans.T_PayMethod,
trans.T_Amount
};

// if Payee and Category selected, get transactions for both
if ((chkbxPayee.Checked) && (chkbxCategory.Checked))
{
if (!string.IsNullOrEmpty(qryPayeeId))
qryTrans =
qryTrans.Where(trans => trans.T_PayeeId ==
qryPayeeId);
if (!string.IsNullOrEmpty(qryCatId))
qryTrans =
qryTrans.Where(trans => trans.T_Category == qryCatId);
}

// if Category selected, get transactions for the Category only
if (chkbxCategory.Checked)
{
if (!string.IsNullOrEmpty(qryCatId))
qryTrans =
qryTrans.Where(trans => trans.T_Category ==
qryCatId);
}

// if Payee selected, get transactions for the Payee only
if (chkbxPayee.Checked)
{
if (!string.IsNullOrEmpty(qryPayeeId))
qryTrans =
qryTrans.Where(trans => trans.T_PayeeId ==
qryPayeeId);
}

dgvSearchResults.DataSource = qryTrans.ToList();
}
 
P

Paolo

Peter: thank you. Yes, I see now that the first 'if' is redundant and I will
remove it - that will 'unclutter' the code.

I'm not so sure about the big 'where' statement - I think doing that will
not aid readability.

Another question if I may. At the moment the results of the search are
displayed in a DataGridView (dgvSearchResults.DataSource =
qryTrans.ToList();) which is on the same Win form as the form which captures
the search criteria. My original thinking was to display the search result in
a DataGridView on a separate form.

What I'm not sure of is whether I can pass the results of the query to a
second form i.e. to make Form2.dgvSearchResults.DataSource =qryTrans.ToList();

Is this possible?

Peter Duniho said:
Is there any way I can avoid the ugly and repetitive 'if' construct shown
below? [...]

Well, the most obvious improvement would be to remove your first if() test
(checking for a payee and category together), since the individual tests
will accomplish the same exact thing, and in fact do a redundant re-query
of the results.

Beyond that, I would just put all your conditions into the "where" clause
for your original query. For example:

where ((trans.T_Date >= qryStart) && (trans.T_Date <= qryEnd))
&& (!chkbxPayee.Checked || string.IsNullOrEmpty(qryPayeeId) ||
trans.T_PayeeId == qryPayeeId)
&& (!chkbxCategory.Checked || string.IsNullOrEmpty(qryCatId) ||
trans.T_Category == qryCatId)

If you're for some reason concerned about the minimal overhead of
examining the CheckBox and filter string states for each element in the
enumeration, you could factor those out of the query, using one of four
different lambda expressions in your where clause depending on the state
of those filters. But I think that that's probably more trouble than it's
worth.

Pete
 
P

Paolo

Peter: I see what you are saying about extra/unnecessary iterations. My data
set is not going to be of 'industrial' proportions and, in that sense,
performance is not an issue. Nevertheless I do like to adhere to 'best
practice' or, at least, efficient coding practice so I will revisit that
'where' statement.

As far as using a second form is concerned I'd use something like this. I'm
struggling with how I can pass an anonymous type (qryTrans) as a parameter:

Form1 code:
private void searchbutton1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.FormClosed += new FormClosedEventHandler(frm2_FormClosed);
frm2.Show();
this.Hide();

// pass query result to Form2
frm2.doSearch(transQry);
}

void frm2_FormClosed(object sender, FormClosedEventArgs e)
{
this.Show();
}

Form2 code:
public void doSearch(?????) // how express parameters for anonymous
type?
{
dgvSearchResults2.DataSource = qryTrans.ToList();
}
 
P

Paolo

Pete: I thought as much. I suppose I could just transfer the query to the
second form and initiate it there when I 'show' that form.

As I'm still learning C#/LINQ, I'm not sure how I'd "return the query result
as a non-generic IEnumerable". Could you give me an example?

Thanks

Peter Duniho said:
[...]
As far as using a second form is concerned I'd use something like this.
I'm
struggling with how I can pass an anonymous type (qryTrans) as a
parameter:

You can't. The compiler only knows the anonymous type in the method where
it was declared.

Now, you should be able to return the query result as a non-generic
IEnumerable, and depending on how the other form is using it, that could
be enough. But if not, you should probably consider just not using an
anonymous type. It's simple enough to create an appropriate named type
that you can then reference in both classes. It would be possible to use
reflection, but that's an awful solution for something dealt with so
trivially through conventional techniques.

Pete
 
P

Paolo

Pete: many thanks - that's brilliant. I'll need to cogitate on it a bit (as I
said, I'm still learning!) but I think, together with the various books I'm
using to learn C#/LINQ, I'll be able to develop a workable solution based on
your example.

Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top