The Self-Taught Programmer

Recipes from real-world experience with asp.net.

How to Convert a Generic List to a Comma-Delimited List

leave a comment »

The Situation:

You have a List<string> and need to convert it to a comma-delimited list (for display or storage).

A Solution:

This is a great example of how C# has improved over the years. I found this solution in this StackOverflow discussion and don’t want to lose it, so I am copying it here for reference.

List<string> strings = <code>...;

// .NET 2.0:
string joined = string.Join(",", new List<string>(strings).ToArray());

// .NET 3.5:
string joined = string.Join(",", strings.ToArray());

// .NET 4.0:
string joined = string.Join(",", strings);

Thanks to Jon Skeet, Xavier Poinas and the rest of the guys that participated in that discussion. Gotta love StackOverflow!

Advertisements

Written by Jim McMullen

March 25, 2013 at 11:32 am

Posted in How-To

Tagged with ,

How to Add a New Table to an Existing Database via EF Code-First Migrations

leave a comment »

The Situation:

You have been using Entity Framework code-first migrations with an existing database. Making changes to an existing table, such as adding a new field, go smoothly, and the database is updated correctly when you run an “Update-database” command. However, when you create an entirely new entity in your model and run “Update-database”, the new table doesn’t get added to your database. You get the “No pending code-based migrations” message.

A Solution:

I spent some time today researching this on StackOverflow and other forums and came up with no solution. It wasn’t until I started to think through the details of the process that EF migrations goes through that I found the answer.

EF migrations use a Configuration.cs file, which specifies an EF dbContext to use in communicating with the database. The context file lists all the entities that it manages. Therefore, you must add the new entity to the context file!

Once you add it to the context, EF migrations can “see” it and add it to the database.

Written by Jim McMullen

February 19, 2013 at 3:41 pm

Posted in How-To

Tagged with

How to Enable and Use EF Code-First Migrations for Multiple Contexts

with 4 comments

The Situation

You want to use Entity Frameworks code-first migrations to push model changes to the database, but you have multiple databases and contexts in your model. When you try to run Enable-Migrations for the second context, you get an error that looks like this:

Migrations have already been enabled in project 'Project1'. To overwrite the 
existing migrations configuration, use the -Force parameter.

If you go ahead and use the “-force” parameter, it will overwrite your Configuration.cs file for the 1st context, which isn’t what you want.

A Solution

The work-around for this is to rename the Configuration.cs file that is generated on the first run and to give it its own namespace. Here are the steps I took:

1) I keep my data access code separate from my UI by putting it in a separate project and referencing it from my UI project. To make Enable-Migrations work properly, I had to temporarily make my data access project my startup project by right-clicking on the project in the Solution Explorer and clicking on “Set as startup project”. (You won’t need to do this if your contexts are in the same project as the rest of your application.)

2) In the Package Manager Console, run this command:

Enable-Migrations -EnableAutomaticMigrations -ContextTypeName NameOfFirstContext

3) A Migrations folder will be added to your project with a Configuration.cs file in it. Rename the file. Maybe something like “ConfigurationContext1.cs”.

4) Now open the Configuration.cs file and change the namespace. I added the name of the context to the namespace.

This is important. Giving each configuration file its own namespace will make sure that migrations are only applied to the correct context. If you don’t do this, the Update-Database command will look at ALL the pending migrations and try to apply them to the current context. This could result in an error (such as “Unable to generate an explicit migration because the following explicit migrations are pending:“) or tables might be added to/deleted from the wrong context/database.

5) In the Package Manager Console, run the same command for for the next context:

Enable-Migrations -EnableAutomaticMigrations -ContextTypeName NameOfSecondContext

6) Repeat the above steps for each context that you need to enable migrations.

7) Rename the new Configuration.cs file, maybe “ConfigurationContext2.cs”.

To update the database with changes to your model, simply specify the configuration file to use for the update like this:

Update-Database -ConfigurationTypeName ConfigurationContext2

Written by Jim McMullen

February 14, 2013 at 11:14 am

Posted in How-To

Tagged with

How To Make a Column in an ASPxGridView ReadOnly for Editing but Enabled when Inserting a New Record

leave a comment »

The Situation:

You have a DevExpress ASPxGridView on your page with a column designated as “ReadOnly=true”. This works great when you are editing an existing record — it won’t allow you to change that field, but when you try to insert a NEW record, you can’t enter anything in the field.

Note: I don’t know if this happens under all circumstances, but for me, it happened for an ASPxGridView that is databound via code rather than from a datasource object on an aspx page.

A Solution:

The simple solution for this problem is to handle the “oncelleditorinitialize” event of the ASPxGridView.

Here is (simplified) ASPxGridView in my aspx page:

<dx:ASPxGridView ID="ASPxGridView1" runat="server" AutoGenerateColumns="False"
	KeyFieldName="SettingName" onrowdeleting="ASPxGridView1_RowDeleting"
	onrowinserting="ASPxGridView1_RowInserting"
	onrowupdating="ASPxGridView1_RowUpdating" Theme="DevEx"
	oncelleditorinitialize="ASPxGridView1_CellEditorInitialize">
	<Columns>
		<dx:GridViewCommandColumn VisibleIndex="0">
			<EditButton Visible="True" />
			<NewButton Visible="True" />
			<DeleteButton Visible="True" />
		</dx:GridViewCommandColumn>
		<dx:GridViewDataTextColumn FieldName="SettingName" ReadOnly="true"
			VisibleIndex="1">
		</dx:GridViewDataTextColumn>
		<dx:GridViewDataTextColumn FieldName="SettingValue" VisibleIndex="2">
		</dx:GridViewDataTextColumn>
	</Columns>
</dx:ASPxGridView>

And here is the code called for the oncelleditorinitialize event:

protected void ASPxGridView1_CellEditorInitialize(object sender, ASPxGridViewEditorEventArgs e)
{
	if (ASPxGridView1.IsNewRowEditing)
	{
		if ((e.Column.FieldName) == "SettingName")
		{
			e.Editor.ReadOnly = false;
		}
	}
}

Written by Jim McMullen

February 12, 2013 at 11:16 am

Posted in How-To

Tagged with ,

Entity Framework: Repository or Not Repository?

leave a comment »

On the heels of the demise of the commercial version of EntitySpaces, I am delving into Microsoft’s Entity Framework. I need to implement it in a big project to replace a much more manual Data Access Layer.

So I’ve done a ton of reading on it (and played with it some, too), and the common wisdom is to use the Repository Pattern to implement it. The main reason seems to be to maintain a separation of concerns — so that the persistence layer isn’t directly used/referenced from the UI. In turn, this seems to be important so that you can change the underlying data structure without changing the UI very much.

At first, this seems to add a layer of complexity to an application that doesn’t seem to be necessary — I never used this pattern with EntitySpaces (although I could have), and indeed, the ES developers recommended against it. Entity Framework uses the dbcontext as its own repository/unit of work pattern, so why add a whole other level of abstraction to it? Adding complexity will surely slow down development, and speeding things up is my primary motivation for using an ORM framework.

There is a terrific case made for NOT using repositories by Oren Eini (aka Ayende Rahien), a contributor to the NHibernate open-source ORM framework. His post can be found here.

Will I ever actually change the database layer?

As I said, this doesn’t seem to be necessary – I don’t believe I will change the underlying database from SQL Server to Oracle or some other database. Even if I did, Entity Framework can work with many different databases.

I suppose there is a possibility that it could change to a web service implementation. I don’t know why the project would change like that, but it could if the need arose. In this case, repositories would insulate the UI from that change. I am implementing EF using POCOs, so those could be kept and reused even with web services.

But What If I Change the UI?

But after thinking about it for a while, the most important reason to maintain separation of concerns in my project is that I don’t know how the UI layer will change. I can already see the possibility of creating several UIs – Web, mobile, and public web services. Aha! If I use repositories, I can develop as many UIs as I want using the same data access layer. Or almost the same data access layer — I am certain I would have to add custom methods to my repositories for each UI.

But can I still create multiple UIs if I don’t use repositories — using EF directly? Yes, of course I can. On the downside, there will be some duplication of code. Conversely, the data access will be tailored directly to my UI needs.

So what’s the right answer?

Guess what, despite the legions of fanatics that will tell you there is only one “right” way to do it, either way will work.

For speed’s sake, I strongly considered going without repositories, but I have decided to use them based on the multiple examples of their effectiveness and my uncertainty about future UI development for my project.

Written by Jim McMullen

February 1, 2013 at 10:32 pm

Posted in How-To

Tagged with

How to Find the Index of an Object in a List

leave a comment »

The Situation

You are trying to find out if an object exists in a List object.

A Solution

Use Linq. The example below looks for a User object in a List<User> by searching for the UserName:

private int FindObjectInList(List<User> list, string uName)
{
    return list.FindIndex(s => s.UserName == uName);
}

Written by Jim McMullen

February 1, 2013 at 10:23 pm

Posted in How-To

Tagged with ,

How to Pass Extra Parameters When Using AJAX Toolkit CascadingDropDowns with a Database

leave a comment »

The Situation:

You have set up your CascadingDropDowns as shown on the ASP.NET AJAX Control Toolkit documentation here, using a web service to retrieve and populate your dropdowns. However, in addition to the value of the first dropdown, you need to pass other parameters to the web service to be used in your query.

A Solution:

The CascadingDropDown control has a mechanism for this — ContextKey. You can add it like at design time like this (note the last 2 lines):

<ajaxToolkit:CascadingDropDown
	ID="CascadingDropDown3"
	runat="server"
	TargetControlID="dd2"
	ParentControlID="dd1"
	PromptText="Please select blah blah blah"
	ServiceMethod="GetDDdata"
	ServicePath="WebSerivce.asmx"
	Category="ObjectName"
	UseContextKey="true"
	ContextKey="0" />

This works great for passing a single parameter. And you can set it dynamically in the code-behind like this (make sure to include a “using AjaxControlToolkit;” in the code-behind):

CascadingDropDown ccd = (CascadingDropDown)CascadingDropDown2;
ccd.ContextKey = avalues + ";";

But what if you want to pass more than a single value?

You can always set ContextKey to a delimited string, which will work just fine. But the AJAX toolkit’s CascadingDropDown control has a function called “ParseKnownCategoryValuesString(string)”, which accepts a string delimited in this way:

“key:value;key:value;key:value;”

And returns a StringDictionary containing the keys and their values, so you can easily use them in your code.

Here’s an example of how to use this in your web service code:

[WebMethod]
public CascadingDropDownNameValue[] GetDDdata(string knownCategoryValues, string category, string contextKey)
{
	// The Value of the parent DropDown is in knownCategoryValues
	StringDictionary kv = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
	int someId;
	if (!kv.ContainsKey("SomeItemName") ||
		!Int32.TryParse(kv["SomeItemName"], out someId))
	{
		return null;
	}

	// Other parameters are in contextKey. Must be formatted the same as knownCategoryValues
	//  (i.e., "key:value;key:value;key:value;")
	StringDictionary ck = CascadingDropDown.ParseKnownCategoryValuesString(contextKey);

	string SomeOtherThing = "";
	if (!ck.ContainsKey("SomeOtherThing") || ck["SomeOtherThing"] == null)
	{
		return null;
	}
	else
	{
		SomeOtherThing = ck["SomeOtherThing"];
	}
	
	// ... do some other processing here ...
	
	return result;
}

Written by Jim McMullen

November 1, 2012 at 12:14 pm

Posted in How-To

Tagged with ,