NHibernate has a lot of interesting and specific option for mapping entities that can really cover every scenario you have in mind, but you need to be aware of every implication each advanced option has on performances.

If you are in a legacy-database scenario where entity A reference Entity B, but someone outside the control of NHibernate can delete record from table used by Entity B, without setting the corresponding referencing field on Entity A. We will end with a Database with broken reference, where rows from Table A references with a field id a record in Table B that no longer exists. When this happens, if you load an Entity of type A that reference an Entity of type B that was deleted, it will throw an exception if you try to access navigation property, because NHibernate cannot find related entity in the Database.

If you know NHibernate you can use the not-found=”Ignore” mapping option, that basically tells NHibernate to ignore a broken reference key, if EntityA references an Entity B that was already deleted from database, the reference will be ignored, navigation property will be set to Null, and no exception occurs. This kind of solution is not without side effects, first of all you will find that Every time you load an Entity of Type A another query is issued to the database to verify if related Entity B is really there. This actually disable lazy load, because related entity is always selected. This is not an optimum scenario, because you will end with a lot of extra query and this happens because not-found=”ignore” is only a way to avoid a real problem: you have broken foreign-key in your database.

My suggestion is, fix data in database, keep the database clean without broken foreign-keys and remove all not-found=”ignore” mapping option unless you really have no other solution. Please remember that even if you are using NHibernate, you should not forget SQL capabilities. As an example SQL Server (and quite all of the relational database in the market) has the ability to setup rules for foreign-key, es ON DELETE SET NULL that automatically set to null a foreign key on a table, when related record is deleted. Such a feature will prevent you from having broken foreign key, even if some legacy process manipulates the database deleting records without corresponding update in related foreign-key.

Gian Maria.

Tags:

No comments

I’ve already blogged how to associate Work Items with TFS Check-ins using tags in comment and a bunch of Api Calls. This feature is now available for any TF Service based on Git, but someone asked me how can you accomplish this task with API. A possible scenario would be supporting different type of comment syntax and in general to understand how this task can be accomplished though API.

The code is really similar to the one I’ve posted in the other article, the only differences is comments are taken from Git commit and not from changeset checkins. The prerequisite is having a local git repository cloned from a TF Service Git based project, than we can simply iterate through all commits to identify comments containing pattern #wid, where wid is the work item id. Once a commit is identified we can create the link between the corresponding Work Item with some API calls.

You can find most of the details in the previous post, in this one I just want to show the section related to Git. First of all to create the link that connect a Work Item to a Git commit you need to have both the guid of the Team Project, and the TFS guid of the Git Repository.

//get a reference to the git repository service
var gitRepoService = projectCollection.GetService<GitRepositoryService>();
var gitProjectRepoService = gitRepoService.QueryRepositories(teamProjectName);
var defaultGitRepo = gitProjectRepoService.Single(gr => gr.Name.Equals(teamProjectName));

//Id needed to create the link
var tpGuid = teamProject.Guid;
var gitGuid = defaultGitRepo.Id;

Git repositories has no concept of a “guid”, but in TF Service the server assign a guid to each Git Repository. Since a Team Project can contain more than one single git repository, in this simple example I take the only one that has the name equals to the Team Project, the default one. In real production scenario you probably should scan all the repositories.

Thanks to LibGit2Sharp obtaining a list of commits is really simple, you need to have a local clone of the repository and you should fetch from origin (TF Service) so you have your local repository origin/master aligned with the server, then you can simply iterate through all commits of the origin.

using (var repo = new Repository(@"C:\Develop\TfService\GitTestProject"))
{

    var remoteCommits = repo.Branches["origin/HEAD"].Commits;
    foreach (var commit in remoteCommits)
    {
        Console.WriteLine("Analyzing commit {0}", commit.Id);
        var comment = commit.Message;
        var matches = Regex.Matches(comment, @"#(?<id>\d+)");
        foreach (Match match in matches)
        {
            //I have an association on the form #changesetid
            var id = Int32.Parse(match.Groups["id"].Value);
            var workItem = workItemStore.GetWorkItem(id);

            //now I should create the link, I need the guid of the team project
            var link = String.Format
                (
                    "vstfs:///git/commit/{0}%2f{1}%2f{2}",
                    tpGuid,
                    gitGuid,
                    commit.Sha
                );

The interesting part is the one that creates a TF Service valid link to the commit to establish a link with the Work Item. The link is composed by a vstfs:///git/commit part, followed by the id (guid) of the Team Project, then a forward slash (encoded so it is %2f), then the TF Service guid of the Git Respository, another forward slash and the sha of the commit (full commit id). The rest of the code simply uses a regular expression to find comment that contains pattern #wid to identify Work Item ids to be connected. Once you create the string representation of the link, you can easily create the link between the Work Item and the commit.

//now create the link
ExternalLink changesetLink = new ExternalLink(
    workItemStore.RegisteredLinkTypes[ArtifactLinkIds.Commit],
    link);
//you should verify if such a link already exists
if (!workItem.Links.OfType<ExternalLink>()
    .Any(l => l.LinkedArtifactUri == link))
{
    Console.WriteLine("\tAssociate changeset {0} to Work Item {1}:{2}",
        commit.Id.Sha,
        workItem.Id,
        workItem.Title);
    workItem.Links.Add(changesetLink);
    workItem.Save();
}

The above code simply check if the work item already was linked to the same commit (to avoid creating duplicate links) and if the link is not present it simply create a new Work Item link of type ExternalLink and the Work Item is connected..

You can use this simple Proof Of Concepts and implement the logic you like to associate Changeset and Work Items. The code is here http://sdrv.ms/107WUgo you can use at your own risk, it is not intended for production use, but only as a guide to familiarize with related API.

Gian Maria.

Tags: ,

No comments

Tags:

No comments

Gian Maria

Tags:

No comments

Code UI Test are an effective way to test your UI through automation, they absolutely are not a substitution for Unit Testing, but they can be used effectively to verify the whole application behave as expected. The most annoying part of Coded UI Test is that while they are running you cannot do anything else on the computer, because mouse and UI are used to run the test. This lead to a very common question

Is it possible to run Coded Ui Test in a Virtual Machine instead that in my primary machine?

The answer is yes, and it is a really simple task to accomplish. First of all install a Test controller on a machine in your network (or a virtual machine if you want to run test inside a local VM) and configure it.

image

Figure 1: Configure user used to run the service and nothing more 

You need only to specify the account used, and you should not register it to a Team Project Collection, just leave any other option blank. Then you need to install Test Agent on the same machine or to another one, and configure that test agent to connect to the previous installed test controller.

image

Figure 2: Configure the agent to log on automatically and connect to the test controller

Now you should see that the Agent component connects to the controller and the Test Agent Status is online

image

Figure 3: The test agent is online and connected to the controller.

It is time to go back to Visual Studio, right-click on the solution name and add new item, from the list of templates choose Test Settings

image

Figure 4: Add a test settings to the solution

Even if in VS 2012 test settings are not used by default as in VS2010 they are still there. In VS 2012 you do not usually need a Test Settings file, unless you want to run tests with some non standard configuration, as in this example. Once you have added a Test Settings file you can edit it and choose to execute test remotely specifying the name of the machine that has the Test Controller installed.

image

Figure 5: Choose to run test with Remote Execution

Now you should simply save the file, and choose as the active test settings browsing for the file

image

Figure 6: Activate test settings

Now if you run again the Coded UI Test it will be run in the machine with the test agent.

image

Figure 7: The VM with test agent runs tests for me

Thanks to this configuration you can execute any Unit Test in a remote machine, not only CUIT.

Gian Maria.

Tags: ,

No comments