Convert Class Library to Database Project

by Chris 2. July 2009 16:40

I’ve had this tendency to deploy CLR Functions manually by providing the dll and scripts to the data management team. This has generally worked out great, and I’ve always thought I’d have a dba available to perform the database duties. Imagine my surprise when I could not contact anyone today. Apparently database administrators take their holidays and vacations seriously (it’s Independence Day weekend for my non-American readers).

Another developer asked me why I couldn’t deploy my clr functions through the IDE. Having never done this, I asked him how. He showed me the deploy button in his project.

Deploy

I went back to my desk, heartened that I could still get my work done. I opened the Solution, right-clicked the project… but there was no Deploy. Thinking back on it, I know that I tend to make class libraries rather than database projects. I looked at my coworker’s project and sure enough, he was using a database project.

It seemed rather heavy-handed to create a new database project and move files over, so I dug into the csproj file to figure out how to convert it.

There are two key things that need to be done to convert a class library to a database project. SqlServer.targets needs to be imported, and the ProjectTypeGuids property needs to be added.

  <Import Project="$(MSBuildToolsPath)\SqlServer.targets" />
  <PropertyGroup>
    <ProjectTypeGuids>{c252feb5-a946-4202-b1d4-9916a0590387};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
  </PropertyGroup>

It doesn’t matter where these entries are added, but I place the property in the top property group below the Platform property and paste the import near the CSharp.targets import. The first guid in ProjectTypeGuids specifies that this is a SqlClrProject. The second guid specifies this is a C# project. Visual Basic developers will need to replace the C# guid with F184B08F-C81C-45F6-A57F-5ABD9991F28F.

The deploy button now appears but doesn’t work. When clicked, it fails with no more information than “Deploy failed.” Deducing that it probably needs a database connection, I used MSDN to find out where that configuration is located. This is one place the MSDN documentation is misleading.

Select Deploy from the Build menu. The assembly will then be registered in the SQL Server instance and database specified when the SQL Server project was first created in Visual Studio.

This is true only if one has never changed that configuration for the Database project. Since this was a class library converted to a database project, the server and database wasn’t specified when creating the project. Luckily, this can be configured in the Properties window on the Database tab. Be sure to add the connection to Server Explorer (Ctrl+W, L) first.

DatabaseProperties

At this point, the project has been converted and we’re almost ready to deploy. Before doing so, the assembly must be dropped from the database. Visual Studio is smart enough to drop it, but only if the assembly was deployed from Visual Studio in the first place. After the first deployment, it will work automatically in the future.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Build Ninja

Embrace the Dark Side

by Chris 30. June 2009 23:57

I’m trying to win the grand prize for June on Community Credit, and I get 5000 points for linking to there. Here’s what I’m trying to win!

DarthVaderUSB

Embrace the Dark Side
Embrace the dark side every day with this animated Darth Vader USB hub. His eyes light up red as he moves his head from side to side and performs his trademark heavy breathing. Push button activation or select random intervals throughout the day. Plug a peripheral in and Vader activates to the sound of a light saber

Remember, if you’re writing blog posts, presenting, or volunteering for the community in any form; you too can win stupid prizes for smart people!

Currently rated 1.0 by 1 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

General

One Public Type Per File

by Chris 30. June 2009 17:52

I remember when I started working on this particular project a few months ago. When I looked over the code for the first time, I noticed something funny about the cs files. Each cs file contained multiple public types. In the extreme cases, there were dozens of public classes in one file.

I brought it up with my new teammates, and one person claimed that he liked to keep related classes in a single file. I mentioned that I find it more difficult to find what I’m looking for in the solution tree, but he shrugged it off by suggesting I use the search feature.

Having never seen this type of code structure before, and with the knowledge that you group related classes by namespace, I decided to research why I felt so strongly that public types deserve their own file. I referred to the Framework Design Guidelines book by Krysztof Kwalina and Brad Abrahams (which is a great reference, btw). The first rule under A.4 File Organization is “DO NOT have more than one public type in a source file.” It then lists a few exceptions (number of generic parameters, nested, etc.).

Today I received yet another reminder of why this type of file structure is bad. I pulled down the latest code, then I retrieved a shelveset I was working on last week. I knew I might have to merge a few files, but I didn’t expect this.

DefinedMoreThanOnce

Ignoring the misspelled class name, someone had moved the type from a file I was working on to another. This kind of silliness wouldn’t happen if the class had its own file. I wasn’t even working on that particular class. As it turned out, the class in question was used by a few xaml pages, and a developer thought it fit better with a different xaml page than its original home.

My rule is one public type per file, using namespaces and project folders to group related types. This reduces the amount of potential editing conflicts and makes it easier to find the type in the Solution Explorer. If you have types with the same name but a different number of generic parameters, name the file by the class name with `(# generic parameters) at the end. For example, List<T> would be List`1.cs.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Kodefu

Prevent Crawlers On Your Data Service

by chris 29. June 2009 17:01

At ConvergeSC 2009, an attendee asked me to describe how to prevent crawlers from trolling your ADO.NET Data Service. I explained as best as I could, but I felt like a blog post might make it more clear.

To a bot, your data service looks like any other site on the web. Sure, it’s reading either Atom, POX, JSON, or some other bizarre format you’ve concocted, but it’s still data coming down through http and discoverable via links. There are ways to prevent a bot from crawling, but information available on the web that doesn’t require authentication can be crawled.

The first way to prevent your service from being crawled by a legitimate bot is to put a Robots.txt in the root of the site. Inside the file, put the following lines:

User-agent: *
Disallow: /

This locks down the entire site from being crawled by the bot. If your service coexists with a site you want to be crawled, you can change the Disallow option to /MyService.svc/. be sure to include the closing slash so other pages aren’t accidentally matched.

The conference attendee seemed to be concerned specifically about anchor tags and AJAX. If you’re using the OnClick event of the anchor tag, most spiders will not follow it. However, if the uri is in an href, a crawler will pick it up. Bing and Google will honor a rel attribute with the “nofollow” value to prevent indexing the page. However, Yahoo and Ask will still follow and index a link with that attribute.

If your service is publicly available, using the robots.txt is the way to go. If it’s not publicly available, the service should already be locked down through authentication techniques.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Kodefu

The Lounge

by Chris 29. June 2009 16:07

I am honored to have joined the Lounge Advertising Network!

Now, I know you’re thinking, “Why would someone be honored to join an ad network?” I would answer that with “look who else is in this network.” The Lounge picks only the top Microsoft technology blogs… blogs by influencers both online and off. To be counted among them is indeed a cool thing.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Tracking Items in Solution Explorer

by Chris 26. June 2009 15:27

Have you ever debugged a large project you didn’t create? If so, you’ve probably gotten lost in the vast jungle of code that was once some poor programmer’s paradise. This vast jungle is full of cannibalistic tribes and wild animals waiting to tear you to pieces. Your only hope for survival is your ability to navigate the solution tree, relying on your wits to circumvent the illogical paths of code that “Go To Definiton” has guided you down.

Luckily, Visual Studio 2008 will provide you a guide if you ask for it. Open Tools | Options… | Projects and Solutions | General. Then, check the box for “Track Active Item in Solution Explorer.”

TrackActiveItem

After you have pressed okay in this dialog, when you have a file opened in the editor, the Solution Tracker will automatically select it. The one catch I’ve found is that if the project is contained within a solution folder, the folder must be open.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Kodefu

KiGG View Detailed Story

by Chris 23. June 2009 18:58

I recently deployed a KiGG site, but I wanted it to act more like DZone than DotNetShoutOut. On DotNetShoutOut, if you click the link from any of non-detailed page views, it takes you to the site. DZone will take you to the detailed view of the story, and if you click the link from there it will take you story’s site. The reason for this change is that I want my site to foster the community: more comments and viewing promoters. Eventually, I would like to code up a friend system for KiGG similar to DotNetKicks friend system, and I feel that seeing who promoted a story will grow more connections between those in the community.

Here’s how you can implement viewing the detailed story. In your KiGG 2.2 release codebase, open up Kigg.Web\Views\Story\Story.ascx. On line 132, you will find the declaration for detailUrl.

<% string detailUrl = Url.RouteUrl("Detail", new { name = story.UniqueName }); %>

Cut this and paste it immediately after the table tag on line 99. Then, replace the first td’s content with the following snippet of code.

<% if (Model.DetailMode) %>
<% { %>
<h2><a class="entry-title taggedlink" rel="bookmark external" 
        href="<%= Html.AttributeEncode(story.Url) %>" target="_blank" 
        onclick="javascript:Story.click('<%= attributedEncodedStoryId %>')">
        <%= Html.Encode(story.Title)%></a></h2>
<% } %>
<% else %>
<% { %>
<h2><a class="entry-title taggedlink" 
        href="<%= Html.AttributeEncode(detailUrl) %>">
        <%= Html.Encode(story.Title)%></a></h2>
<% } %>

That’s it: simple change! I think it would be better to make this configurable and submit it to the project. I may do that when I have more time to sift through the codebase.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Kodefu

Ease The Pain of Office Interop

by Chris 23. June 2009 13:39

If you’re a C# developer who has tried to do Microsoft Office programming, you know how much of a pain it can be. Most of the methods require tons of parameters, and you end up needing to pass tons of Missing.Value argument around.

If you haven’t done this before, it’s easy to get started writing Office programs. First, make sure you have Office installed. Second, add a reference in your project to the Office application you want to automate.

AddReference

Now, add the appropriate using clause (using Microsoft.Office.Interop.Excel;) to your C# code. If you use multiple Office applications, you may wish to alias the namespace to prevent naming conflicts. Most of the Office interops use the same class: Application. Now, create your Excel application object for automation.

var excel = new Microsoft.Office.Interop.Excel.Application();

That was easy enough. Here’s the part where it gets nasty… nearly every method you call requires optional parameters and casting.

Worksheet sheet = (Worksheet)book.Sheets.Add(Missing.Value, 
    Missing.Value, Missing.Value, Missing.Value);

Sheets.Add isn’t so bad, but some methods have dozens of parameters. These only exist to junk up your code. Wouldn’t you much prefer to write the following instead?

Worksheet sheet = book.Sheets.Add();

So would I. In C# 4.0, we get optional parameters and the interop code returns dynamic types, so this is exactly how your code will look next year. But that doesn’t really help us today. Luckily, there is a C# 3.0 feature that will allow you to write readable interop code: extension methods.

public static Worksheet Add(this Sheets sheets)
{
    return (Worksheet)sheets.Add(Missing.Value, Missing.Value, Missing.Value, Missing.Value);
}

Just place that method in a static class and you’re good to go. Then, add methods as you need them. Since you can overload extension methods, you still have the flexibility of optional parameters. Here’s the full class I needed for the piece of Office automation I was working on.

internal static class ExcelExtensions
{
    public static void Close(this Workbook workbook)
    {
        workbook.Close(null, null, null);
    }

    public static void SaveAs(this Workbook workbook, string fileName)
    {
        workbook.SaveAs(fileName, Missing.Value, Missing.Value, Missing.Value, 
            Missing.Value, Missing.Value, XlSaveAsAccessMode.xlShared, Missing.Value, 
            Missing.Value, Missing.Value, Missing.Value, Missing.Value);
    }

    public static Workbook Add(this Workbooks workbooks)
    {
        return workbooks.Add(Missing.Value);
    }

    public static Workbook Open(this Workbooks workbooks, string fileName)
    {
        return workbooks.Open(fileName, Missing.Value, Missing.Value, Missing.Value, 
            Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, 
            Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, 
            Missing.Value);
    }

    public static Worksheet Add(this Sheets sheets)
    {
        return (Worksheet)sheets.Add(Missing.Value, Missing.Value, Missing.Value, 
            Missing.Value);
    }
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Kodefu

SQL Server 2008 Installation Fail

by Chris 21. June 2009 03:52

I was setting up a SQL Server instance on my co-located server, but a series of events led me to uninstall it and reinstall it a few times. The final time through, it detected the original reporting services database, so I cancelled the installation and deleted the SQL Server folders. At that point I spent the next hour or so trying to make SQL Server get past the setup bootstrap installation.

The setup program told me everything was okay before it began the installation. The problem was, the installer just disappeared in the middle (after entering the key, before requesting usernames/passwords): it threw no error, the installation logs said everything was okay, there was nothing in the event logs.

I tried rebooting, but that didn’t work. I tried deleting the registry entries, but that didn’t work either. I checked everywhere I could think of for remnants of SQL Server. I then thought that maybe I dirtied my key with all my install attempts, so I tried to install the developer edition: same problem.

Then it occurred to me to check Programs and Features.

sqlserversetup

Sure enough, the setup program was installed, and it was causing the installer to fail. Uninstalling this fixes the problem.

Currently rated 1.0 by 1 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Kodefu

Refactor ForEach to AddRange

by Chris 19. June 2009 16:31

Here’s a refactoring I used to do some minor cleanup today. The programmer was iterating through a dictionary to add values to a list. No logic was contained within the iterator.

public void AddCodes(Dictionary<int, string> indexedCodes)
{
    foreach (var code in indexedCodes.Values)
    {
        Codes.Add(code);
    }
}

This can be simplified by using the list’s AddRange method.

public void AddCodes(Dictionary<int, string> indexedCodes)
{
    Codes.AddRange(indexedCodes.Values);
}

If you’re reassigning, this is even more unnecessary; just use the ToList method provided by LINQ.

public void AssignCodes(Dictionary<int, string> indexedCodes)
{
    Codes = indexedCodes.Values.ToList();
}

This isn’t much of a change, but it did simplify things. The real world example was surrounded by other blocks of code that made it difficult to read. This one, small change helped improve the readability of the method.

Currently rated 1.0 by 1 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , , ,

Kodefu

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

Whois KodefuGuru

Chris Eargle

Chris Eargle
.NET Community Champion

LinkedIn Twitter Technorati Facebook

MVP - Visual C#
INETA Community Champion

22 events to go... #52ers


World Map

RecentComments

Comment RSS

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2009