Refactor rename on LINQ to SQL Classes 2

This is a quick, dirty work around to renaming the properties of the LINQ to SQL classes. Say you have a simple DBML class you want to rename.

image

Simple enough right? Just click in there and edit the WidgetName to Name right? Wrong! You have code like this.

public Widget CreateNewWidget(string name, string description)
{
    return new Widget {
        WidgetDescription = description,
        WidgetName = name
    };
}

You’re going to abandon all those calls to WidgetName and do a search and replace refactor. That sucks. So rename it to WidgetName2 for now and let all the references break.

image

That breaks our code.

image

Fine for now. Create a partial class for the Widget.cs and add our WidgetName back in

public partial class Widget
{
    public string WidgetName { get; set; }
}

Use ReSharper to rename that property to name.

image

Then delete the partial class, or property and rename the property in the DBML to Name.

Done.

You sneaky deferred execution! 0

As I’ve mentioned we have a series of Extension methods that help with some trivial, but isolated tasks. Here is an example.

public static IEnumerable<SelectListItem> CreatePaymentTypeDropDownListItems(
                                          this IQueryable<PaymentType> @this)
{
    return  @this
            .OrderBy(x => x.Description)
            .Select(x => new SelectListItem
                             {
                                 Value = x.Code,
                                 Text = x.Description,
                             })
            .MarkAsSelected(x=>x.Text == CreditCard);
}

Simple enough right? The MarkAsSelected is another extension method we have to help out. It’s not all that exciting, but here it is.

public static IEnumerable
 MarkAsSelected(this IEnumerable
 @this, Func
 where)
{
    var items = @this.Where(where);
    foreach (var item in items)
    {
        item.Selected = true;
    }
    return @this;

}

Simple enough right? But the credit card payment type was never getting defaulted with the select value. We have unit tests around MarkAsSelected and it works! What’s the problem? Let’s try something really quick.

public static IEnumerable<SelectListItem> CreatePaymentTypeDropDownListItems(
                                          this IQueryable<PaymentType> @this)
{
    return  @this
            .OrderBy(x => x.Description)
            .Select(x => new SelectListItem
                             {
                                 Value = x.Code,
                                 Text = x.Description,
                             })
            .ToArray()
            .MarkAsSelected(x=>x.Text == CreditCard);
}

That works! What’s up? Oh you sneaky deferred execution. I bet it’s you! I’m not an expert, but here is my best guess. When the MarkAsSelected does its foreach, it asks the @this to create an enumerator. It does, but since it is from an IQueryable<T>, it now executes all that deferred execution in the Select and OrderBy. Fair enough. The enumerator spits out all the SelectListItems we want/need.

We pass on the enumerable incase we want to do something after it, and actually we do. Down the road we want to enumerate again. The Select and OrderBy kick in again and we get all brand new SelectListItems.

Throwing that ToArray in there gets us out of operating on the IQueryable<T>, does the Select and OrderBy and lets us operate on a straight list. Makes sense, but not obviously apparent…at least to me.

But you know what? After all that, I think I just prefer this.

public static IEnumerable<SelectListItem> CreatePaymentTypeDropDownListItems(
                                          this IQueryable<PaymentType> @this)
{
    return  @this
            .OrderBy(x => x.Description)
            .Select(x => new SelectListItem
                             {
                                 Value = x.Code,
                                 Text = x.Description,
                                 Selected = (x.Description == CreditCard)
                             });
}

No need to overcomplicate the problem right?