June 2008 - Posts

In ASP.NET, I try to develop in a "black box," often trying to keep the dependencies with methods small.  This technique creates a low "fan-in" or loose coupling that makes the code easier to maintain in the future.  With that said, there can be some grey lines when it comes to this arena.  For instance, when creating methods, I like to pass in object-references:

public IEnumerable<LinqClass> GetResults(Customer customer)

Rather than:

public IEnumerable<LinqClass> GetResults(int customerKey, bool isPreferred)
{
  
}

This is because each of the parameter details are stored in the customer object, whereas anytime the criteria changes for GetResults, it requires the developer to break the interface of the method.  However, the approach I prefer doesn't work well with some of the featured controls, like the ObjectDataSource.  The ObjectDataSource looks to pass in primitive data, with a few exceptions.

Sometimes I wonder just what is the right level of encapsulation.  For instance, suppose I had this method:

public void LoadCustomers(GridView grid)
{
    CustomerBAL bal = new CustomerBAL();
    grid.DataSource = bal.GetCustomers();
    grid.DataBind();
}

This method encapsulates what work is being performed on the grid, while allowing multiple grids to be called with this method (if that is a good thing in this scenario).  However, I think maybe doing it this way:

public void LoadCustomers()
{
    CustomerBAL bal = new CustomerBAL();
    this.gvwCustomers.DataSource = bal.GetCustomers();
    ths.gvwCustomers.DataBind();
}

This encapsulates what the action is performed against (I don't need to know that it's binding to a grid), but it's not as flexible because it only happens for one grid control, which I think in most situations is better.

But I don't really know which one is better in this situation, but I know one thing; I think I'm overthinking it too much Big Smile!!  Any opinions on the subject, or other examples you would like to share?

Posted by bmains | with no comments
Filed under:

 I had an issue where I had a locked file in VS 2008, and I couldn't compile a project because it couldn't copy a DLL from obj/debug to bin folder.  Something that worked for the issue was something Roy Osherove posted about here:  http://weblogs.asp.net/rosherove/archive/2008/04/09/fix-cannot-copy-file-x-to-file-y-the-process-cannot-access-the-file-because-it-is-being-used-by-another-process-in-visual-studio-2008.aspx

This code renames the file by appending a .locked at the end of the file.  I can copy the project that was causing me problems.  Thanks Roy!

Posted by bmains | with no comments
Filed under:

 Some people may not be familiar with the use of the new "var" keyword.  The easiest way to explain it is: whatever your evaluation or return type of a method is, this is what the data type is.  If you do:

var values = CallSomeMethod(); //returns IEnumerable<int>

The values variable equates to IEnumerable<int>.  If you use a LINQ query:

var values = from c in Customers select c; //returns IQueryable<Customer>

The values variable is of the IQueryable<Customer> type, unless you use a LINQ to SQL method to transform the data as in the following:

var values = (from c in Customers select c).First(); //returns Customer
var values = (from c in Customers select c).ToList() //returns List<Customer>

In this case, the values are of a specific type returned from the method; in the case of LINQ queries, it infers the type as a collection based type (even if one result is returned; it can't know that at design time).  Because it can infer the type at design time, it knows what the type is and can give you intellisense.

However, if you assign it a null value, it will give you a design-time error.  This is because the compiler can't determine the underlying type.  At runtime, the value can be null, but not at design time.

Posted by bmains | with no comments
Filed under:

I don't know if anyone has come across this, but I ran into an interesting issue today.  I had done this LINQ query in C#:
 
from c in store.Customers
where c.IsActive = true
select c;
 
What I was trying to accomplish is find all of the customers where the active flag equals true (straight equality check).  What happened is all the records came back; this was because I used one equal sign, instead of two, and it actually assigned the values in the record, without giving me a compile error.
 
Very interesting...

Posted by bmains | with no comments
Filed under:

I had an issue using AsQueryable() in some of my code.  What I was trying to do is this:

CustomerDAL customers = new CustomerDAL(this.DataContext);
short key1 = customers.GetPrimaryContact(selectedCustomer).CustomerKey;
short key2 = customers.GetSecondaryContact(selectedCustomer).CustomerKey;
return new short[] { key1, key2 }.AsQueryable();

The results were returned to the keys variable, and I used them in a query like so:

where ...
&& !keys.Contains(c.CustomerKey)  //produced StackOverflowException

But this kept throwing a stack overflow exception, and I couldn't figure out why.  I would comment out that line above and it would work without that contains.  Later I figured out that AsQueryable() was the problem; simply removing it, and returning an IEnumerable result worked perfectly.  So be careful with AsQueryable in your use of it; in some scenarios, it may be a problem.

If someone knows the reason why, please post a comment, as I would be interested to know what that is an issue.

Posted by bmains | 1 comment(s)
Filed under:

As software developers, we try to keep reusability in mind.  To figure out whether a particular solution is reusable, take a look at what you have to do to use it.  For instance, if you are developing an ASP.NET user control, does the developer who consumes that user control have to only write 2, 20, or 200 lines of code for it to work?  If you create a custom server control, do I have to configure 5 settings for the bare minimum to work, or 100?  Is your code a 1:1 correlation between the product code and the consumer code, or 1:100 (100 lines of product code for every 1 line the user of that component has to implement)?  Is the setup easy to do, or is it too complicated?  Is it very general or very detailed in setup?

Some solutions are labeled as reusable but require you to do as much work as the reusable component.  In this situation, developing a wrapper around this component is a good idea.  THis allows you to make the component more reusable by putting your implementation code and any common setup code in the wrapper, thereby saving extra coding effort.  So in my previous example, 2 lines to reuse code is great; 20 is probably practical (unless the reusable code is 20 lines or less itself), and 200 lines to implement reusable code probably needs refactoring.

In this day and age, if it isn't simple to use, people won't use it at all.

Posted by bmains | with no comments
Filed under:

I found this a while ago about using dynamic LINQ in your code.  This really works well with the ASP.NET GridView (and other data bound controls) where sorting is supported.  Because, when a column header is clicked, the Sorting event fires with the details of the sort.  The event argument contains the field being sorted in string form (it's actually the name of the column stored in the column setup).

Because LINQ is strongly-typed, Dynamic LINQ allows a string name to be provided, which uses reflection to parse against the underlying type, and pass in the field that correponds to the SortExpression parameter.  In this way, Dynamic LINQ allows sorting without a huge if..else statement in the Sorting event handler.  It works really easily.

Use the following for sorting:

protected void grid_Sorting(object sender, GridViewSortEventArgs e)
{
    var dataSource = this.GetDataSource();
    dataSource = dataSource.OrderBy(e.SortExpression + " " + e.SortDirection.ToString().ToLower());

    this.BindGrid(dataSource);
}

The order by statement using dynamic LINQ takes a string for the column name, but it also parses the text to look for an ascending or descending statement (I made it lower case because I saw it looked for lowercase text, and I didn't see that it lowered the text automatically).

Posted by bmains | 2 comment(s)
Filed under: