Archive for the ‘.NET’ Category

Query MS CRM XML Entity with XQuery and LINQ

In our company we have been working on a large MSCRM 2011 project. Last week, I was asked to create a report listing all the visible fields for each entity in the solution. During my search, I found a few different ways to do it, but the most fun way was querying the XML.
The XML is created when the solution is exported. It’s normally several levels deep and even when the structure would depend on the solution the XML listed below is an example of how it would looks like.

<Entities>
    <Entity>
      <Name LocalizedName="Account" OriginalName="Account">Account</Name>
      <ObjectTypeCode>1</ObjectTypeCode>
      <EntityInfo>
        <entity Name="Account">
          <LocalizedNames>
            <LocalizedName description="Account" languagecode="1033" />
          </LocalizedNames>
          <LocalizedCollectionNames>
            <LocalizedCollectionName description="Accounts" languagecode="1033" />
          </LocalizedCollectionNames>
          <Descriptions>
            <Description description="Business." languagecode="1033" />
          </Descriptions>
   <attributes>
		<attribute PhysicalName="Category">
			…
	<attribute>
   </attributes>
</entity>
      </EntityInfo>
   <FormXml>
        <forms type="main">
          <systemform>
            <formid>{b053a39a}</formid>
            <form>
              <hiddencontrols>
                <data id="addressid" datafieldname="addressid" classid="{}" />
                <data id="address2” datafieldname="address2" classid="{}" />
              </hiddencontrols>
		  <tabs>
                <tab name="general" verticallayout="true" id=”" IsUserDefined="0">
                  <labels>
                    <label description="General" languagecode="1033" />
                  </labels>
                  <columns>
                    <column width="100%">
<sections>
  <section name="account information" showlabel="false" showbar="false" id="{}" IsUserDefined="0">
                          <labels>
                            <label description="Information" languagecode="1033" />
                          </labels>
                          <rows>
                            <row>
                              <cell id="{}">
                                <labels>
                                  <label description="Name" languagecode="1033" />
                                </labels>
                                <control id="name" classid="{}" datafieldname="name" />
                              </cell>
                              <cell id="{}">
                                <labels>
                                  <label description="Phone" languagecode="1033" />
                                </labels>
                                <control id="telephone1" classid="{}" datafieldname="telephone1" />
                              </cell>
                            </row>
                            <row>
                              <cell id="{}" showlabel="false" >
                                <labels>
                                  <label description="Contact" languagecode="1033" />
                                </labels>
                                <control id="primarycontactid" classid="{}" datafieldname="primarycontactid">
                                  <parameters>
                                    <FilterRelationshipName>customer_accounts</FilterRelationshipName>
                                    <DependentAttributeName>parentcustomerid</DependentAttributeName>
                                    <DependentAttributeType>account</DependentAttributeType>
                                    <AllowFilterOff>true</AllowFilterOff>
                                  </parameters>
                                </control>
                              </cell>
                              <cell id="{}" showlabel="true" >
                                <labels>
                                  <label description="Other Phone" languagecode="1033" />
                                </labels>
                                <control id="telepho" classid="{}" datafieldname="telep" />
                              </cell>
                            </row>
                            <row>
                              <cell id="{}">
                                <labels>
                                  <label description="Parent" languagecode="1033" />
                                </labels>
                                <events>
                                  <event name="setparams" application="true" active="true">
                                    <InternalHandlers>
                                      <Handler handlerUniqueId=" " enabled="true" />
                                    </InternalHandlers>
                                  </event>
                                </events>
                                <control id="parentaccountid" classid="{}" datafieldname="parentaccountid" />
                              </cell>
                              <cell id="{ }">
                                <labels>
                                  <label description="Fax" languagecode="1033" />
                                </labels>
                                <control id="fax" classid="{}" datafieldname="fax" />
                              </cell>
                            </row>
                            <row>
                              <cell id="{ }">
                                <labels>
                                  <label description="E-mail" languagecode="1033" />
                                </labels>
                                <control id="emailadd" classid="{}" datafieldname="emailadd" />
                              </cell>
                              <cell id="{ }">
                                <labels>
                                  <label description="Web Site" languagecode="1033" />
                                </labels>
                                <control id="websiteurl" classid="{}" datafieldname="websiteurl" />
                              </cell>
                            </row>
                          </rows>
                        </section>
             </sections>
                    </column>
                  </columns>
                </tab>
</tabs>
</form>
     </systemform>
        </forms>
      </FormXml>
    </Entity>
</Entities>

'

Take into consideration that we have several entities and those entities have multiple tabs, sections, controls and labels. The listing above is just an example of what MS CRM exports in XML format. It shouldn’t be consider as a real entity. Having said that, lets continue with the real fun.

My task was to find all the visible and enabled fields in the solution. I also needed to know, if the fields belong to the Account entity or any other entity and I just needed to retrieve the fields from the Main form not the Mobile form.

Before we go further, is important to say that I had to retrieve the Label description, but I had to check the cell element, “Showlabel” attribute which controls the visibility as you can see on the next example.

<cell id="{}" showlabel="true" >
  <labels>
    <label description="Other Phone" languagecode="1033" />
  </labels>
  <control id="telepho" classid="{}" datafieldname="telep" />
 </cell>

'

Like I said before, there are different ways to do this. Here are a couple examples.
The first I used was XQuery and FLWOR expressions.

Basically it searches through the XML verifies if the “showlabel” attribute is either not there or set to true and retrieves the names.


SELECT ent.vals.value('@OriginalName', 'varchar(max)') AS Entity, ent.vals.value('@datafieldname', 'varchar(max)') FieldName
FROM @xml.nodes('for $en in //Entity
return ($en/Name,(for $q in ($en/FormXml/forms/systemform/form/tabs/tab/columns/column/sections/section/rows/row/cell)
where (empty($q/@showlabel) or ($q/@showlabel=&amp;quot;true&amp;quot;))
return $q/control)) ') ent(vals)

'

It returns the Entity name in one column follow by the Fields. It looks like this:

Another way to query is using Linq to XML. The statement looks like this:


var xrmEntities =   from e in doc.Elements(&amp;quot;Entity&amp;quot;)
                        from c in e.Elements(&amp;quot;FormXml&amp;quot;).Elements(&amp;quot;forms&amp;quot;).Elements(&amp;quot;systemform&amp;quot;).Elements(&amp;quot;form&amp;quot;)
                                    .Elements(&amp;quot;tabs&amp;quot;).Elements(&amp;quot;tab&amp;quot;)
                                    .Elements(&amp;quot;columns&amp;quot;).Elements(&amp;quot;column&amp;quot;)
                                    .Elements(&amp;quot;sections&amp;quot;).Elements(&amp;quot;section&amp;quot;)
                                   .Elements(&amp;quot;rows&amp;quot;).Elements(&amp;quot;row&amp;quot;)
                                    .Elements(&amp;quot;cell&amp;quot;)
                        where (string)c.Attribute(&amp;quot;showlabel&amp;quot;) == &amp;quot;true&amp;quot; || c.Attribute(&amp;quot;showlabel&amp;quot;) == null
                        from l in c.Elements(&amp;quot;labels&amp;quot;)
                        let formName = e.Element(&amp;quot;Name&amp;quot;).Attribute(&amp;quot;LocalizedName&amp;quot;).Value
                        let fieldName = l.Element(&amp;quot;label&amp;quot;).Attribute(&amp;quot;description&amp;quot;).Value
                        orderby formName, fieldName
                        select new {Entity = formName, Field = fieldName };
    xrmEntities.Count().Dump();
    xrmEntities.Dump();

//”doc”  variable loads the XML file.

The result returned by Linq is probably easier to understand. It looks like this.

Either way returns the Fields Names so, It’s up to you to decide what to use Linq or XQuery. Both of them are good things to learn as a developer.

Tags: , , , , , , , ,


CRM 2011: Dynamically Filter a Lookup Based on Multiple Joins

There are times when you would like to filter a Lookup based on the selected value of another Lookup, but those entities do not have a direct relationship to each other. For instance, I had a situation where there was a Work Item Tracking entity that had Lookup fields for both a Project and Work Item Type entity. Based on what the user selected for the Project and the Work Item Type’s “Default” value, the Work Item Type Lookup needed to be filtered.

Work Item Type Form

However, there is no direct relationship between the two; Work Item Types are associated with Projects via a Program entity. So, I basically needed to create a view for the Work Item Type Lookup that only showed records with a Default of “Yes” and also joined to Projects through Programs. The problem I ran into, though, was that I mistakenly thought that I would need to set things up so the view would join from the Work Item Type to the Programs, then to the Projects where the Project was equal to the currently-selected Project, then back to the Programs, then finally back to the Work Item Type, where I could filter by Default.

That would’ve been fine if the result set was pulled from the Work Item Type join at the end, but it’s pulled from the original Work Item Type reference. So, a less convoluted approach was needed: I had to filter by Default, but also join from Work Item Type to Programs, then to Projects where the Project was equal to the currently-selected Project. Throwing it together in a Personal View, it looked like this:

Filtered View

From there, it was a matter of grabbing the FetchXML so I could use it in an OnLoad JavaScript function to dynamically replace the “projectid” value and name:

<?xml version="1.0"?>
-<fetch distinct="true" mapping="logical" output-format="xml-platform" version="1.0">
	-<entity name="workitem">
		<attribute name="workitemid"/> <attribute name="name"/> <attribute name="createdon"/> <order descending="false" attribute="name"/> -<filter type="and">
			<condition attribute="default" value="1" operator="eq"/>
		</filter> -<link-entity name="program" alias="aa" to="programworkitemid" from="programid">
			-<link-entity name="project_program" to="programid" from="programid" intersect="true" visible="false">
				-<link-entity name="project" alias="ab" to="projectid" from="projectid">
					-<filter type="and">
						<condition attribute="projectid" value="{AB6FCB73-6F1C-E111-B786-005056BC4F66}" operator="eq" uitype="project" uiname="Test 4"/>
					</filter>
				</link-entity>
			</link-entity>
		</link-entity>
	</entity>
</fetch>


Regarding the specifics of actually creating the custom view, it’s basically just building the FetchXML string, getting the Lookup control, then using “addCustomView” to set it, but all of that is covered in a great article at Create a custom filtered lookup view in runtime – CRM 2011.


Disable copy and paste with jQuery

Occasionally the need arise to prevent users from copying text from one field and pasting it in another on a Web form. Especially when dealing with confirmation fields such as passwords and email addresses where you want the user to retype the value previously entered to prevent typos.

Using jQuery it’s more intuitive and becomes a trival task with the bind event, which attaches one or more events to a given handler. You simple pass a string with the event types you’re interested in, space separated, to the bind call and include preventDefault to cancel the default behavior. For example, to prevent the cut, copy and paste operations on the Password field, you can use the following code.

$(document).ready(function() {
    $('#Password').bind('cut copy paste', function(event) {
        event.preventDefault();
    });
});

The event handler can take parameters, as in the case above, but it’s often not needed as sufficient context is usually available when the handler is bound. However, there are times when it’s necessary to gather additional information at the time the event was raised. For example, to determine the operation that the user attempted in the function about, you can use the event.type. See the event object documentation for more information.

Tags: , , , ,


Denali New T-SQL features.

SQL Server Denali comes with a number of new features that will help to make our life easier or more complicated depending on your point of view. However, I think it will make our life a lot easier.

A few of the new features that I will talk about today are the Try/Catch block, execute a store procedure With Result Sets and the IIF function.

TRY/CATCH

It was originally introduced in SQL 2005. However it lacked flexibility and we were not able to re-throw the error like we do it in C# or VB.net. However, now we can using “THROW”. Here is an example of how it works:

DECLARE @REG VARCHAR(50);
DECLARE @MORE INT;

	BEGIN TRY
		SELECT @REG= RegionDescription FROM DBO.Region R
		INNER JOIN Territories T ON T.RegionID = R.RegionID	 

		SELECT @MORE= @REG

	END TRY

	BEGIN CATCH
		PRINT 'You need to cast the varchar before assign it to a int';
		THROW;

	END CATCH

This is just a simple example of how it works, however there are many different ways to format the message so you can display or return the right message for your code or UI. You can find additional information at Microsoft

WITH RESULT SETS

Another new feature that was called to my attention is the execution of stored procedures “WITH RESULT SETS”. With this new feature you won’t need the high cost efficient functions. Something else that is nice with this feature is that you can rename the columns returned by the stored procedure. Also if you were using a temp table in order to see the data you will not need it any more with the new “WITH RESULT SETS.” Here is an example:

-- Create the store procedure in the Northwind database
CREATE PROCEDURE [dbo].[spTerritories] (@Region int)
as
BEGIN
	SELECT TerritoryID, TerritoryDescription, RegionID FROM Territories
	WHERE RegionID = @Region
END
GO

EXEC spTerritories @Region = 1
WITH RESULT SETS
(
	(
		PlaceID varchar(100),
		PlaceDescription text,
		Region float
	)
)

Now, regarding cost, the new approach is a lot more efficient than the previous versions. In fact if you run something like this:

DECLARE @TestTable TABLE (TerritoryID varchar(MAX), TerritoryDescription text,
    RegionID float )

INSERT INTO @TestTable
EXEC spTerritories @Region = 1

SELECT * FROM @TestTable

It will cost you around 5 times more than just executing the store procedure With Result Sets. Take a look at the image below.

The blue square is the execution of the store procedure with the result sets that was 14% of the batch. The red squares make a total of 14 + 57 + 14 = 85% of the whole batch, so there is no doubt that using WITH RESULT SETS is more efficient that the old way.

IIF Function

Another new feature in SQL Denali are the built in functions. I will not write about all of them but you can find great examples of them at Pinal Dave’s blog. You can find a reference to his blog at the end of this post.

The one that caught my attention was the new IIF function. It basically replaces the Case statement for simple scenarios. Obviously if you have a long nested IIF function the CASE may be your best option. However the new IIF improves the code a lot.

Here are a couple of examples using tables from the Northwind database.

SELECT IIF(RegionID >= 2, 'Good Region', 'The best') as RegionScore,
		TerritoryID, TerritoryDescription, RegionID
FROM  dbo.Territories

Another example would be something like this. In this case I’m nesting the IIF function.

SELECT IIF(RegionID >=2,
		IIF(
			(SELECT e.FirstName
			FROM  Employees  e
			LEFT JOIN EmployeeTerritories et
                            on e.EmployeeID = et.EmployeeID
			WHERE et.TerritoryID =ttr.TerritoryID) is null, 'No Data',
			(
			        SELECT  e.FirstName
				FROM Employees  e
				LEFT JOIN EmployeeTerritories et
                                    on e.EmployeeID = et.EmployeeID
				WHERE et.TerritoryID =ttr.TerritoryID
		       )
			),'No Employee Assigned') as RegionScore,
		TerritoryID, TerritoryDescription, RegionID
FROM  dbo.Territories  ttr

Some of the other built-in functions are specified on Pinal’s website. You can take a look at them Clicking Here. Microsoft is another reference for any information I wrote on this post.

Tags: , , , , , , , ,


C# Regex Multiple Replacements

As I was testing the XML request for web service, I would periodically get a response back: [400]: Error parsing xml. After some troubleshooting, I discovered that the error was caused by a few of the Predefined XML Entities included in the actual data. The most common issue was the ampersand “&” being embedded in the Address and Account data.

I needed a way to replace those xml entity characters, but didn’t want to replace each one separately, so I thought, great I’ll just use a Regular Expression.

The Regex.Replace method has 4 overloads, but the basic syntax in .NET is Regex.Replace(string input, string pattern, string replacement). That didn’t work for me because I needed the replacement value to vary, based on the pattern.

For example, this simple replacement…Regex.Replace(input, "&", "&")…wasn’t what I wanted as that would mean repeating it for the other replacements. Now the pattern can include multiple items, for example Regex.Replace(input, "&|\”|<|>|’", replacement), but the replacement would be the same for each one, so I needed to use the overload that accepts a MatchEvaluator delegate that is called each time a regular expression match is found during a Replace operation.

Regex.Replace(string input, string pattern, MatchEvaluator evaluator)

Given that my search and replace values were simple, I decided to use a generic Dictionary and store the entity and its replacement as name value pairs.

var xmlEntityReplacements = new Dictionary<string, string> {
    { "&", "&amp;" },
    { "'", "&apos;" },
    { "<", "&lt;" },
    { ">", "&gt;" },
    { "\"", "&quot;" }
};

Great, now I can revised the Regex like this:

Regex.Replace(input, "&|\"|<|>|'", delegate(Match m) {
    return xmlEntityReplacements[m.Value];
})

Not bad, but I am duplicating the items in the pattern (they are already in the dictionary) and why use the anonymous method approach when I’m using .NET 3.5 and have access to LINQ? So a little refactoring was in order.

Ok, but I need to get the dictionary Keys and return then as a pipe-delimited string. There is a CopyTo() method on the collection to convert the Keys or Values to an array, and from the array I can get the string I needed. That’s good, but I don’t want to have to declared and array to house the values and then use CopyTo, that’s an extra step. Hmmm, another great use for LINQ and its extension methods:

Regex.Replace(source, string.Join("|", xmlEntityReplacements.Keys
    .Select(k => k.ToString()).ToArray()), m => xmlEntityReplacements[m.Value])

Here’s the code converted to a method.

/// <summary>
/// Replaces the 5 predefined entities in XML with the appropriate
/// name/escape character.
/// </summary>
/// <param name="source">string to search</param>
/// <returns>source string with replaced value or original string</returns>
public static string ReplaceXmlEntity(string source)
{
      if(string.IsNullOrEmpty(source)) return source;

      // The XML specification defines five "predefined entities" representing
      // special characters, and requires that all XML processors honor them.
      var xmlEntityReplacements = new Dictionary<string, string> {
            { "&", "&amp;" },
            { "'", "&apos;" },
            { "<", "&lt;" },
            { ">", "&gt;" },
            { "\"", "&quot;" }
      };

      // Create an array and populate from the dictionary keys, then
      // convert the array to a pipe-delimited string to serve as the
      // regex search values and replace
      return Regex.Replace(source, string.Join("|", xmlEntityReplacements.Keys
          .Select(k => k.ToString()).ToArray()),
              m => xmlEntityReplacements[m.Value]);
}

Note, for more complex patterns/searches, the dictionary approach won’t work as the MatchEvaluator would expect to find the match as a Key in the Dictionary and it wouldn’t be there. For example, let’s say your match pattern was “T.p” (T followed by any character then a lowercase p), the replacement value was “Top” and the input string was “Just Tap and Tip.” The dictionary would have a Key of “T.p” and a Value of “Top” Now, the pattern “T.p” is going to match both “Tap” and “Tip” but those words aren’t Keys in the dictionary and you’d get the error “The given key was not present in the dictionary.”

I’ll leave that as an exercise for you to do if you so choose.

Tags: , , , ,


SQL 2005: Adding and modifying XML node attributes

There’s a change we’re making to one of our projects that relies on a couple new XML attributes, however, we already have data in our development system that we want to keep. While the XML would be updated when the project saves it, nobody wants to manually open and click through the 2000+ forms we’ve generated over the past couple years, so I ended up creating a sproc that would do it for us.

My first thought was that I could simply cast the value from the XML column as a VARCHAR(MAX), fire off a couple global REPLACE commands, and be done with it, but things are never that easy. While one of the attributes we were adding could be inserted with the same value for all nodes, the other holds the ID of the tab the control the node represents is rendered on. This means I needed to figure out a way to select individual nodes and insert the attribute with the correct value, which means REPLACE was out of the question.

I settled on loading a cursor with the node ID’s and their corresponding tab ID’s, then using XQuery to modify individual nodes with the correct values. It’s not the quickest solution, but it did exactly what I needed; I could pick out a specific node, check if the attribute already existed, then add/modify as needed:


	DECLARE @xml XML
	DECLARE @Query VARCHAR(MAX)
	DECLARE @FVId INT
	DECLARE @FFId INT
	DECLARE @FVSId INT

	SELECT	 @xml = FIData
			,@FVId= FVId
	FROM FI
	WHERE FFId = @FFId

	DECLARE fvff_cursor CURSOR FOR
	SELECT fvff.FFId, fvff.FVSId
	FROM fvff
	INNER JOIN fvs ON fvs.FVSId = fvff.FVSId
	INNER JOIN fvt ON fvt.FVTId = fvs.FVTId
	WHERE fvt.FVId= @FVId
	AND fvff.Active = 1

	OPEN fvff_cursor

	FETCH NEXT FROM fvff_cursor
	INTO @FFId, @FVSId

	WHILE @@FETCH_STATUS = 0
	BEGIN
		IF @xml.exist('/formData/FFValues/FF[@FFId=xs:string(sql:variable("@FFId")) and @FVSId]') = 0
		BEGIN
			SET @xml.modify('insert attribute FVSId{ xs:string(sql:variable("@FVSId")) } into (//formData/FFValues/FF[@FFId=xs:string(sql:variable("@FFId"))])[1]')
		END

		IF @xml.exist('/formData/FFValues/FF[@FFId=xs:string(sql:variable("@FFId")) and @IsEnabled]') = 0
		BEGIN
			SET @xml.modify('insert attribute IsEnabled{ "true" } into (//formData/FFValues/FF[@FFId=xs:string(sql:variable("@FFId"))])[1]')
		END
		ELSE
		BEGIN
			SET @xml.modify('replace value of (//formData/FFValues/FF[@FFId=xs:string(sql:variable("@FFId"))]/@IsEnabled[.="false"])[1] with "true"')
		END

		FETCH NEXT FROM fvff_cursor
		INTO @FFId, @FVSId
	END

	CLOSE fvff_cursor
	DEALLOCATE fvff_cursor

	UPDATE FI
	SET FIData = @xml
	WHERE FIId = @FIId

WCF, Entity Framework and N-Tier Solutions – Part 3

Create the Silverlight Application

If you’ve read my two previous posts on the subject, (Part 1 and Part 2) you will know that I promised to do a part 3 to this series that will show how to wire up what we did in creating our N-Tier solution using WCF and Entity Framework to an actual application. In this case, we will create a Silverlight application that can consume our WCF services and display them on a page. This will not be as long as the other two posts, but it should give you a general idea of how this is to be done.

The first order of business is to create a new Silverlight application. In this case, we are going to add it to the solution that we created in the previous posts. It is called “BurnNotice”. Once again, if you do not know what Burn Notice is, my heard bleeds for you … check it out here … but it won’t affect your understanding of the example. To do this, right click on the solution itself and choose the option “Add > New Project” as shown in the screenshot.

 

The “Add New Project” dialog box will appear and you can select any kind of Silverlight application that you would like, but I generally like to choose the “Silverlight Navigation Application” as it comes pre-wired with some pages and navigation controls. You can make your own by adding additional controls in the same manner.

 

After selecting the type of Silverlight application that you want, you will be presented with the “New Silverlight Application” dialog. This will allow you to host the Silverlight application inside of a web application that Visual Studio will create for you. Assuming that you have not already added a web application to your solution, you can accept most of the default values. Of course you can name it whatever you want. My options were as follows:

 

After you have clicked the “OK” button, Visual Studio will add two new projects to your solution. The first of the two will be the Silverlight application from which you will connect to WCF Services created previously. The second will be the web application to host your Silverlight application so that it can be viewed in a browser. For the purposes of debugging, you will want to have the web application as the default project. If you selected the “Silverlight Navigation Project”, then you will also see a basic UI setup in the Design pane as shown in the following screenshot.

 

The web application project will have two pages designed to host your Silverlight application, one a web form and the other a standard html page like so:

 

The names of these two pages will be abnormally long as they include the name of the project along with “TestPage” added to the end. You don’t need to change them, but if you are going to be typing the address into a browser, it makes sense to change the name of the page to something more standard. I personally got rid of the html page altogether and then renamed the web form to “default.aspx” like this:

 

Add a Reference to the WCF Service

At this point we are almost home free. The last step to actually use the service that we created previously is to add a reference to the Silverlight project. In this case, instead of adding a standard reference, though, we want to add a reference to the service itself. To do this, right click on the project name and select “Add Service Reference…” as shown below:

 

This will bring up the “Add Service Reference” dialog box. In the Address box, enter the local URL of the service that you created, unless, of course, you have already deployed it somewhere in which case you can reference it there. After entering the URL, click on the “Go” button and any services discovered at the URL will be listed in the “Operations” box on the right. If none appear then either the URL you entered is incorrect or the service itself is not functioning properly as shown in the screenshot. You will also need to enter the Namespace which you want the reference to belong to. This can also be called whatever you want, but the default will have the word “service” in it so that later, while programming, you will know at a glance that any of the methods inside of it are from a service as opposed to another local project.

 

After adding the service, you will now see a new folder in your project called “Service References” and below it you will find the service that you have just created. It will be named whatever you called the namespace in the “Add Service Reference” dialog. It will look like so:

 

Call the service to populate a Silverlight control

At this point, the only task left is to call the service and use the data returned to populate a control. To do this, open one of the .xaml pages that were created when the Silverlight application was created. Since this is only an example it does not particularly matter which one. In my case, I will do it on the “Home.xaml” page. Once the page is opened in the design view, open the “Toolbox” on the left side of the page as shown in the screenshot. Under the sub heading “Common Silverlight Controls” you will see one called “DataGrid” (not to be confused with the “Grid” control which is used for layout purposes). Click on the DataGrid icon and drag it onto the designer surface.

 

This should end up giving you some code that looks basically like this:

<navigation:Page x:Class="BurnNotice.UI.Home"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
    Title="Home"
    Style="{StaticResource PageStyle}" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

    <Grid x:Name="LayoutRoot">
        <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">
            <StackPanel x:Name="ContentStackPanel">
                <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="Home"/>
                <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}" Text="Home page content"/>
                <sdk:DataGrid AutoGenerateColumns=True" Name="dgSpies" />
            </StackPanel>
        </ScrollViewer>
    </Grid>

</navigation:Page>
 

Right now, I am not going to go into a tutorial on .xaml files or how to acutally create and lay out a page using silverlight, but I do want to show how easy it now is to call the actual service and populate the grid. You will notice that I am just letting Silverlight autopopulate everything for the sake of simplicity. Obviously all of that can be customized. So, in the code behind to the .xaml page, all you need to do is set up some code in the “OnNavigatedTo” event that will call the service. All calls to a service like this are done asynchronously so once the call is done, you also need to set up a delegate that will be invoked when the results from the service are returned. This is very easy to do and the events are built into the service that we have already created. The code to do this looks like so:

namespace BurnNotice.UI
{
    public partial class Home : Page
    {
        public Home()
        {
            InitializeComponent();
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            BurnNoticeServiceClient client = new BurnNoticeServiceClient();
            client.Characters_GetAllCompleted += new EventHandler<Characters_GetAllCompletedEventArgs>(Characters_GetAll_Completed);
            client.Characters_GetAllAsync();
        }

        private void Characters_GetAll_Completed(object sender, Characters_GetAllCompletedEventArgs e)
        {
            dgSpies.ItemsSource = e.Result;
        }
    }
}
 

Depending on the speed, you might notice a bit of a lag time between initially calling the service and having the grid populated, but after it is called and the delegate executed … Voila, you have a populated datagrid on a silverlight page that looks like this (notice that Tricia Helfer is mentioned in the grid … Ahhh Tricia).


Manipulate file names with the Path class

During a recent .NET project I was tasked with building a UI that would allow users to upload a file to the server which would later be parsed and imported into a database table. The process was simple enough:

  1. Select a file to import:
    D:\Renewals\August2011.xml
  2. Copy selected file to a shared folder on the server:
    \\DevServer\Attachments
  3. Pass the file name to an import routine for processing:
    \\DevServer\Attachments\August2011.xml

However, the file selected in step 1, includes the root path which has to be modified before passing to step 3 so that the source file for importing is retrieved from the server and not the user’s system. It’s basic string manipulation and it’s easy to start parsing manually: search for the last backslash, extract the file name or the path and combine/rebuild as needed. I started doing just that when I remembered that the System.IO.Path class has a large assortment of static methods for dealing with strings containing file and path information.

For example, let’s take the file name and folder mentioned above and apply a few of the common methods from the Path class.

var selectedFile = @"D:\Renewals\August2011.xml";
var targetFolder = @"\\DevServer\Attachments";

// Gets the file name: August2011.xml
var fileName = Path.GetFileName(selectedFile);

// Gets the directory name: D:\Renewals
var directoryName = Path.GetDirectoryName(selectedFile);

// Gets the root path: D:\
var root = Path.GetPathRoot(selectedFile);

// Changes the extension of the file: D:\Renewals\August2011.txt
var newFileName = Path.ChangeExtension(selectedFile, "txt");

// Combines a series of strings into a path:
// \\DevServer\Attachments\August2011.xml
var sourceFile = Path.Combine(targetFolder, fileName);

A nice feature of the Combine method is that it’s overloaded to take put to 4 strings (or an Array of strings) and it will add a trailing backlash between the strings if needed. For example:

Path.Combine(@"D:\Renewals", "August2011.xml")
    returns "D:\Renewals\August2011.xml"

Path.Combine(@"D:\Renewals", "Attachments", "August2011.xml")
    returns "D:\Renewals\Attachments\August2011.xml"

Working with strings that include file or directory path information is much easier with path class and you no longer have to resort to manual parsing.

P.S. Rick Strahl posted a great article titled Making Sense of ASP.NET Paths that summarizes the path options along with descriptions for the current request, control and application.

Tags: , , ,


New SQL “Denali” is here

Technology users are growing around the world, as well as data and device dependency , whether it be pc, laptop , tablet or smart phone. Even when the economy doesn’t look very promising, generally speaking there are some other sectors that are not being hit as hard as others, technology is one of them. In fact many websites such as CNMBC.com, USNEWS.com and others are ranking technology carriers as the most growing carriers in the market right now. Demand on this career is growing exponentially as well as tools to supply such demand.

One of the new tools just releases for testing is “Denali”. This is new version of Microsoft SQL Server. This new version is cloud-ready information platform and looks pretty processing. It has the ability to interact with OData and sync information between multiple platforms.

Microsoft is also promising that the OS patching and downtime can be reduced significantly by 50-60% less by running SQL server on Windows Server Core.

Regarding the performance, Microsoft is introducing In-Memory Column Store or better known as “Apollo” on this version. Basically Apollo brings together the Vertipaq technology that was developed in Analysis Services and a new quory excecution paradigm called batch processing to provide speed up for common data warehouse queries.

Some other features that new Denali brings up are:

  • “Crescent”, is a reporting services project. According to Microsoft, it is easy to use and provides with highly interactive web-based data exploration, visualization, and presentation experience to users of all levels.
  • BI Semantic Model which is a single model for user with multiple ways of building business intelligence solutions.
  • “Juneau”, is the project for SQL Server Developer Tools. Actually “Juneau” unifies the development for database development across Database, BI and web and supports SQL Server and SQL Azure.

In order to install Denali there are some requirements you have to take in consideration:

  • First Denali does not install or enable Windows PowerShell; however Windows PowerShell 2.0 is an installation prerequisite.
  • .Net 3.5 PS1 is a requirement and you have to enable .NET framework 3.5 SP1 before you install Denali if you are installing it on a Windows Server 2008 R2 .Net 4.0 is a requirement too.

Regarding hardware and OS Denali can be installed on a Windows Server 2008 and 2008 R2 SP1, Windows 7 SP1 and Vista SP2. It requires a minimum of 1 GB on memory and a 64 version requires a 1.4Ghz process or a 1.0 GHz process if you install the 32-bit version.

Installing Denali was not a big problem. However it took more than 30 minutes installing.

When I start using it I didn’t noticed a big difference between this version and 2008 R2 Version. Here is an email of the new Management Studio UI.

The new UI is powered by Visual Studio so you will fell that you are working on it instead of regular SQL Management Studio.
In future blogs I will discuss about new TSQL features and Reporting tools as well as BI tools that Denali provides.

If you are interested on download and Install Denali you can download it from: Microsoft
Also if you want to learn more about it this video may help you. It talks about new Denali features. The speaker is Dandy Weyn and I can tell that he does a great job presenting the product.
Take a look at it. Microsoft Technet Videos

Tags: , , , ,


Random Error Message: The request for [this] procedure failed because [it] is a table valued function object

While working on a project recently, I ended up needing to call a “Table-valued Function” in SQL Server. Had I been writing my process from scratch, I would probably not have chosen to use a Table-valued function, but I was asked to tap into previously existing code that was, so I didn’t have much choice. Initially, I didn’t think that this would be a problem, however, when I started trying to actually call a Table-valued Function like you would a stored procedure or a Scalar-valued Function, I ended up getting the following error:

The request for procedure ‘Procedure X’ failed because ‘Procedure X’ is a table valued function object
 
 

This error is actually pretty self-explanatory. You can’t call a Table-valued function from ASP.NET. The problem was … I needed to call one. I tried all kinds of things. My last resort was going to be to create a new stored procedure (which I CAN call from ASP.NET) whose only function is to turn around and call the Table-valued function. This did not seem to be a very effective solution to me, if for no other reason than that it would require editing the new stored procedure every time the Table-value function changed. Those kinds of things are easy to get out of sync.

I did search for this error on line and I didn’t find much in the way of solutions. I finally found something that worked though and I thought that I would write a quick blog post about it. In essence, Table-valued Functions are called in the same way that one would run a query against a table. In other words, you use the function as if it were a table. So, if we want to select all the episodes from the BurnNotice Episodes table from season 2 where the rating is 5 stars, then our query would look like this:

SELECT * FROM episodes WHERE rating = 5 AND season = 2

NOTE: This would return a list of all episodes from season 2 as they are all awesome

 

However, if the rating of a given episode were an aggregate of a variety of factors and happened to include several values from different places, we could write a Table-valued Function called “EpisodeRatings” accepts two parameters (@Rating and @Season) that returns all the values that we need. Rather than an EXEC statement which we would use for a Scalar-valued Function, our call would look like this:

SELECT * FROM episoderatings(5, 2)
 

Knowing this difference is actually the key to solving the error that is the subject of this post. Rather than try to call the Table-valued Function as if it were a stored procedure, we will build a parameterized text string in our C# code. Using a parameterized string allows you to dynamically build the SQL Statement in your C# code, but it also uses strongly typed input parameters which would thwart attempts at SQL Injection attacks. I don’t think that this is the ideal solution, but for one of those time in which the project’s requirements or prior design constrain your options, it certainly works. So, below I have an example of some code that will build the SQL String, add in the parameters and then execute the Table-valued Function and return a data table.

public static DataTable ExecuteTableValueFunction(string database, List<SprocParameter> parameterList)
{

	StringBuilder sb = new StringBuilder();

	// Build the parameterized sql string
	sb.Append("SELECT * ");
	sb.Append("FROM episoderatings(");
	sb.Append("@Rating");
	sb.Append(",@Season");
	sb.Append(")");

	DataTable dt = new DataTable();
	Database db = DatabaseFactory.CreateDatabase("BurnNotice");
	DbCommand cmd = db.GetSqlStringCommand(sb.ToString());

	cmd.CommandType = CommandType.Text;
	cmd.CommandTimeout = timeout;

	foreach (SprocParameter param in parameterList) {
		if (param.Value == null) {
			db.AddInParameter(cmd, param.Name, param.DataType, DBNull.Value);
		} else {
			db.AddInParameter(cmd, param.Name, param.DataType, param.Value);
		}
	}

	db.CreateConnection().Open();
	dt.Load(db.ExecuteReader(cmd));
	db.CreateConnection().Close();

	return dt;
}
 
 

So, to conclude … I must say that I did not love solving this issue in this manner. I don’t like building SQL in my code using strings, still it is parameterized and will guard against SQL Injection attacks. In the end, I thought that it was a better option that creating extra procedures simply to call the table valued function. If you are having this error and have no other choice than to barrel forward using a table valued function, I hope that this post helps you solve the problem.