Sunday, September 27, 2009
kick it on DotNetKicks.com Shout it

We are pleased to make our Official EntitySpaces Q3 Release available. Both the Developer and Source code are available for download to current customers and the Trial version is the official ES2009 Q3 production release as well. The version number is 2009.2.0928.0. We recommend you download ES2009 Q3 saving it to disk and then install via the Start menu’s “Run As …” command and run as “Admin”. This is necessary for Windows Vista and Windows 7.

NOTE: You must regenerate your “Generated” classes and your stored procedures, if using stored procedures.

The EntitySpaces 2009 Q3 release has some of the best support for Silverlight and WCF that any ORM has to offer. Our smart proxies are very powerful and make working with WCF services and Silverlight a breeze. See the PDF’s in our Silverlight and WCF demos. Also, our DynamicQuery API is much more powerful in this release. Here is a quick list of features, fixes, and enhancements that are in this release.

The release notes can be found in this PDF file. There are some breaking changes with our 0209 Production Release which is unusual for us, however, they are pretty minor.

  • Sybase SQL Anywhere Support Including the Compact Framework
  • Excellent Silverlight and WCF Support
  • 64 bit runtime assemblies are included
  • A New EntitySpaces.DynamicQuery Assembly which is Silverlight Compliant
  • A New EntitySpaces Generic Concurrency Mechanism for all databases
  • DynamicQuery - The Having Clause is Now Supported
  • DynamicQuery - Full Expressions in OrderBy and GroupBy
  • DynamicQuery - Daisy Chaining Syntax has been fixed
  • DynamicQuery - Supports “Raw SQL” Everywhere
  • DynamicQuery - Sub Operator Ordering Fix
  • DynamicQuery - Order of Values More Flexible
  • DynamicQuery – Serializable in XML (very tiny packets)
  • DynamicQuery – Parse() method allows you to get the SQL without executing the statement
  • Major Proxy Stub Enhancements (WCF/WebServices/Silverlight) and Compact XML Mode
  • Enhanced UserData.xml file (support for multi dabase developers)
  • Editing User Metadata Easier through the .NET Property Grid
  • Connection Configuration Information Enhancements (no longer read only, catalog/schema added)
  • VistaDB and Microsoft SQL CE Password Bug Fixes
  • Microsoft SQL CE “TOP” syntax fixed
  • There is now a Twitter toolbar button on the “Whats New” tab
  • In the Settings “Other” tab you can control what double-click means for a template.
  • In the Settings “Other” tab you can turn off the DateTime stamp in the header.
  • Brand new Silverlight and WCF Demos
  • We are now bound to VistaDB 3.4.1.84

Of course, there are many other internal changes not listed in the above list.

One thing we didn’t get completed is “path relative project files”. We know this is a very important feature however it turned out be be more complicated than we first thought. However, this will be a high priority for 2010. Also, the Trial version comes with the source code to our Sybase plugin for our code generation engine which will allow you to easily switch Sybase versions. The ES2009 Q3 Developer does not have the Sybase source in it, we will make it available via a separate download.

We will be doing a series of blog posts highlighting a lot of these new features so stay tuned.

 

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Silverlight/WCF application, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Sunday, September 27, 2009 9:32:03 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Monday, September 07, 2009

Better Naming Logic

This is a non-breaking change and won’t effect your current codebase. Take a look at this SQL table, notice that the table name and column names are full of funky characters and such …

CREATE TABLE [dbo].[Crazy Names # 123 !(*]
(
    [PrimaryKey#] [int] IDENTITY(1,1) NOT NULL,
    [ Field With Spaces ] [nchar](10) NULL,
    [123FieldStartingWithANumber] [nchar](10) NULL,
    [Field with % Special # Characters , In It) ] [nchar](10) NULL,
    [A Field] [nchar](10) NULL,
    [A_Field] [nchar](10) NULL,
    [StandardFieldName] [nchar](10) NULL,
    [_wow_this_is_crazy.man ok] [nchar](10) NULL,
    [this#dba##should###be####fired#####.ok] [nchar](10) NULL,
    [_ALIAS_ME_#$%] [nchar](10) NULL,
)

This is what the resulting class looks like (in the past, we didn’t handle these so well)

[Serializable]
abstract public class esCrazyNames123 : esEntity
{
    public System.Int32? PrimaryKey;
    public System.String FieldWithSpaces;
    public System.String _123FieldStartingWithANumber;
    public System.String FieldWithSpecialCharactersInIt;
    public System.String AField;
    public System.String A_Field;
    public System.String StandardFieldName;
    public System.String _Wow_This_Is_CrazyManOk;
    public System.String ThisDbaShouldBeFiredOk;
    public System.String MyAlias;
}

You may have noticed the last field “MyAlias” is different. That is because we Aliased it to ensure Aliasing still works. Aliasing is done via the Metadata tabl. You might also notice that “underscores” were left in the column names. However, this is not the default. We merely check the “Preserve Underscores” checkbox because of the “A Field” and A_Field” columns so they wouldn’t conflict. “Preserve Underscores” if off by default. Take a look at this screen shot.

image

Notice on the “Naming Conventions” tab we have “Preserve Underscores” checked. Also, you might notice the “Trimlist” field is completely gone, it is not used anymore. But don’t worry, these changes will not effect your current objects.

Here are the rules basically for Property names in .NET


if(Char.IsLetterOrDigit(character))
{
    // this character is valid
}

The only exception to this rule is you can have an “_” underscores and the 1st character cannot be a number. That’s it. So now, no matter how things are created in your database EntitySpaces will always generate valid classes that compile out of the box, no need for aliasing unless you want to.

 

DynamicQuery Parse() Method

You can now capture the SQL Syntax a DynamicQuery would generate without having to execute it. This is done via the Parse() method like so:

CrazyNames123 c = new CrazyNames123();
c.Query.es.Top = 1;
c.Query.Where(c.Query.MyAlias == "asdf");
string str = c.Query.Parse();

This can come in handy when writing your queries …

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Silverlight application, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Monday, September 07, 2009 9:29:09 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Tuesday, August 11, 2009

Things are going great. We now have all of our data providers upgraded and compiling clean, including the Compact Framework providers. We have many users working fine with our Sybase support so we are very pleased on how our Sybase support is being received. This is just a quick post to let you know we have added the Having clause to fill out our DynamicQuery API.

Here is a sample query (this might not make sense as a real query, this was just for testing the syntax, the query did return data however).

EmployeeQuery q = new EmployeeQuery();
q.Select(q.EmployeeID, q.Age.Sum().As("TotalAge"));
q.Where(q.EmployeeID.IsNotNull());
q.GroupBy(q.EmployeeID);
q.Having(q.Age.Sum() > 5);
q.OrderBy(q.EmployeeID.Descending);

EmployeeCollection coll = new EmployeeCollection();
if (coll.Load(q))
{

}

This resulting SQL is shown below:

SELECT [EmployeeID] AS 'EmployeeID',SUM([Age]) AS 'TotalAge'  FROM
[ForeignKeyTest].[dbo].[Employee]
WHERE[EmployeeID] IS NOT NULL
GROUP BY [EmployeeID]
HAVING SUM([Age]) > @Age2
ORDER BY [EmployeeID] DESC

Our DynamicQuery API has such terrific enhancements coming in ES2009 Q3. Also, our release dates have been posted on our Roadmap. Start making your plans today …

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Silverlight application, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

 

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Tuesday, August 11, 2009 9:00:51 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Tuesday, July 28, 2009

This little gem was brought up by one of our customers, Paul_IBSoftware, and it looked like fun to implement so we snuck it into our Q3 release. Nothing like getting a suggestion and having it in the product the same day. Basically, we had the SQL conjuctions AND and OR but we didn’t have anyway to indicate AND NOT or OR NOT but that is no longer true, see the example below.

VB.NET

Dim q As New EmployeesQuery()
q.es.Top = 1
q.Where(q.EmployeeID = 1 And Not (q.LastName = "goofy"))
q.Load()

Notice you can now use And Not/Or Not in your query syntax. This will yield the following SQL syntax.

SELECT  TOP 1 *
FROM [Employees]
WHERE ([EmployeeID] = @EmployeeID1 AND NOT [LastName] = @LastName2)

C#

You can do this in C# too, however this is one case where the VB.NET syntax reads better than the C# syntax. Take a look at the sample below.

EmployeesQuery q = new EmployeesQuery();
q.es.Top = 1;
q.Where(q.EmployeeID == 1 && ! (q.LastName == "googy"));
q.Load();

Granted, a C# developer would probably never think of that syntax, but it yields the exact same SQL as above. Probably a C# developer would write it as below

EmployeesQuery q = new EmployeesQuery();
q.es.Top = 1;
q.Where(q.EmployeeID == 1 && (q.LastName != "googy"));
q.Load();

The above query would product the following SQL.

SELECT  TOP 1 *
FROM [Employees]
WHERE ([EmployeeID] = @EmployeeID1 AND [LastName] <> @LastName2)

Summary

The EntitySpaces 2009 Q3 DynamicQuery is going to blow your socks off. We are so excited about this release, things are moving very quickly too.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Silverlight application, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Tuesday, July 28, 2009 6:31:17 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Wednesday, July 08, 2009
kick it on DotNetKicks.com

Okay, we finally got it!! We can honestly say getting a grip on Silverlight has been a real learning curve for our team, but it’s going to be a breeze for EntitySpaces customers because we’ve done all the research and laid all of the track. Our first approach was to use strings for everything because we didn’t want to use the “brain dead” proxies created by Visual Studio when you add a service reference to a Silverlight project. Then we figured out how we could force Visual Studio to use our client side proxies when adding a service reference. This is truly awesome. I cannot imagine a better way to write Silverlight applications than with EntitySpaces. What we are about to show you is so easy it will floor you. We will also be making a video on this and making our demo available with a future alpha or beta version. Okay, enough hype, show us already !!

image

Above, is our Silverlight Solution that contains everything needed to run the entire demo. Notice first, that we have all of the EntitySpaces runtime projects included rather than just references to the dlls (EntitySpace.Core35, etc.). We do this as we develop so we can debug and fix things if need be. Naturally, these project references are not required in your solution. You only need to add the runtime dll references to the project which houses your WCF service, EntitySpaces.SilverlightApplication.Web in this case.

Also notice the first project in the red box, EntitySpaces.Proxies.Silverlight. This is simply a Silverlight class library that we added to our solution. Then we generated our client side proxies into that solution. So now we have our client side proxies housed in a Silverlight class library. We could have just added these to our SilverlightApplication but there is a very important reason we didn’t. More on this later. These are generated via our Client Side Proxy Stub Template.

Next we have the SilverlightApplication project itself. This is the Silverlight application that runs in the browser. It references our EntitySpaces.Proxies.Silverlight class library that houses our client side proxies, and it references the EntitySpaces.DynamicQuery.Silverlight assembly because we want to be able to run full “es” DynamicQueries under Silverlight. Of course this project also contains our Page.xaml.cs file which contains our code that executes everything under Silverlight, we’ll be looking at that in a moment.

Finally, we have our EntitySpaces.SilverlightApplication.Web project which houses our WCF service in a web application. The two important files we’ll be looking at here are the INorthwind.cs file and the Northwind.svc.cs file.

Let’s start with the WCF Service

image

We have two methods. GetEmployees takes a serialized query in string form (the only time we have to use strings is with a query) and returns the data through our server side proxy class “EmployeesCollectionProxyStub”. Our Save method takes and returns a server side “EmployeesCollectionProxyStub” as well. The server side proxy stubs are generated via the Generated Master template. You indicate that you want them created via the Proxy/Stub tab as shown below. Also, be sure and check the “Serializable Queries” checkbox on the advanced tab.

image 

 

You can see how simple our WCF Service is in this example. Let’s look at the Northwind.svc.cs file.

image

First, look at the second method, our SaveEmployees() method. Could this be any easier? Not only do you not have to worry about which rows are added, modified, or deleted, but you can simply call Save, and return the very same collection. All new records, including their identity columns and such, will be returned to the Silverlight application so it can update it’s grid (in our case).

The GetEmployees method is a little more complicated, but not by much. It merely deserializes the string (a serialized proxy query) into a full blown EmployeesQuery, asks the EmployeesCollection to load it, then creates an EmployeesCollectionProxyStub class, passing in the EmployeesCollection, and returns it. Pretty simple really.

The Silverlight Application Logic

Let’s take a look at what our Silverlight Application looks like.

image

What the demo application does is create an EntitySpaces DynamicQuery when the user clicks on the Search button, calls our WCF service method GetEmployees(), then populates the grid with the data. The user can edit the data in the grid, and then merely click the Save button, which calls the WCF service method SaveEmployees(). Again, pretty simple.

So let’s look at our page.xaml.cs file. (We’ve removed any error handling to make the screen shot smaller.)

image

Notice in SearchButton_Click we create a EmployeesQueryProxyStub and use it exactly as we do with our full server side DynamicQuery objects, only we cannot load it directly. It must be serialized and sent to the server. In the last line of that method, we call our WCF service method GetEmployees().

In service_GetEmployeesCompleted() we assign e.Result to “employees”, which is our client side EmployeesCollectionProxyStub object, then we bind to employees.Collection, and our grid is populated.

Now, in the save button click event we intentionally set the first rows’ name to “GoogyGaga”, then add an additional Employee just for kicks, and call our WCF service method SaveEmployees(), which returns a refreshed collection, which we again assign to “employees”, and rebind the grid.

That’s it folks. An entire Silverlight application using EntitySpaces, showing both sides of the conversation. EntitiySpaces not only provides the glue between Silverlight and WCF, but it also provides all of the database access as well. All generated in mere seconds from your database schema via our Visual Studio Add in. Does it get any better than this?

Making Visual Studio Use the EntitySpaces Proxies instead of Visual Studio Generated Proxies

This is very cool indeed. We do not want to use Visual Studio generated proxy classes because they do not maintain row state for us (and other things). Our client side proxies maintain what rows are modified, added, and deleted such that you can send the entire collection back to the server and simply call Save() on it and bingo, it’s in the database. Here’s the trick. Remember the EntitySpaces.Proxies.Silverlight class library that houses our client side proxies? Well, there’s a reason we needed to have it housed in it’s own Silverlight class library and that is so we could tell Visual Studio to use it rather than generate proxies for us. Here’s how you do that when adding your Service Reference to the Silverlight application.

image

This is how we add our reference above. However, the trick to forcing Visual Studio to use our client side proxies is performed by pressing the “Advanced …” button.

image

Notice here that we tell it to reuse the types in our EntitySpaces.Proxies.Silverlight assembly. This is totally awesome. It’s great that Visual Studio allows us to do this. But even better, we were somewhat ahead of our time. Our client side proxies easily serialize into our server side proxies and vise versa. This is exactly what the DataContractSerializer is all about. It allows you to have different classes on each side of the conversation, and it works wonderfully in EntitySpaces.

Summary

This may seem like a lot to soak in but it really isn’t. We’ll be shipping our Silverlight demo hopefully with our next Alpha. Writing Silverlight applications is so graceful using EntitySpaces. Sure, you’re going to need to learn XAML and other things but all of the plumbing, wiring, and track have been laid for you. EntitySpaces has terrific Silverlight support. Everything you see here in this blog post works in our current alpha version. It’s late and we need to get some sleep, we are really jazzed about this and if anything we are understating how fantastic EntitySpaces is at providing the glue between Silverlight and WCF.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Tuesday, July 07, 2009 11:43:13 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, July 05, 2009

kick it on DotNetKicks.com

[UPDATED – SEE EntitySpaces, Silverlight, and WCF a Fantastic Combination FOR OUR NEW AND FAR SUPERIOR APPROACH]

Besides the enhancements mentioned in the DynamicQuery Enhancements post, this release addresses some important issues discovered in our previous alpha concerning Silverlight and WCF. You should uninstall the prior alpha before upgrading. Our Silverlight assembly is now named EntitySpaces.DynamicQuery.Silverlight.dll. There is, also, a new class called esDataContractSerializer (available in the .NET 3.5 assemblies) that can be used in any WCF or Silverlight application. Take a look at the code sample below which demonstrates an entire conversation from Server to Client and back to the Server again.  Using this approach all of your methods would use strings to send data to and receive data from the server. Of course, you can use the auto generated proxy classes created by Visual Studio but the nice thing about this approach is that the row-state of all of the data is maintained automatically and then saving becomes trivial.

public void TestCollection()
{
    EmployeesCollection coll = new EmployeesCollection();
    coll.Query.SelectAllExcept(coll.Query.Photo);
    coll.Query.es.Top = 3;

    if (coll.Query.Load())
    {
        // Create Our Server Side Proxy Stub
        BusinessObjects.EmployeesCollectionProxyStub server = new BusinessObjects.EmployeesCollectionProxyStub(coll);

        // Serialize it into a XML string and return this string to our Silverlight or WCF Client
        string xml = esDataContractSerializer.ToXml(server);

        // Deserialize the string above into our Client Side Proxy under Silverlight or our WCF Client
        Proxies.EmployeesCollectionProxyStub client = esDataContractSerializer.FromXml(xml, typeof(Proxies.EmployeesCollectionProxyStub))
            as Proxies.EmployeesCollectionProxyStub;

        // Set a property and notice that esRowState goes to Modified
        client.Collection[0].LastName = "Squarepants";

        // Serialize our Client Side Proxy into xml and send it back to the server
        xml = esDataContractSerializer.ToXml(client);

        // Deserialize it on the server back into a Server Side Proxy Stub, the esRowState is modifed as we would expect
        BusinessObjects.EmployeesCollectionProxyStub server1 = esDataContractSerializer.FromXml(xml, typeof(BusinessObjects.EmployeesCollectionProxyStub))
            as BusinessObjects.EmployeesCollectionProxyStub;

        // Now save the Entity
        server1.GetCollection().Save();
    }
}

You can also use this same approach with the single entity based proxies. For example, the EmployeeProxyStub class.

Some Silverlight / WCF Code

The PopulateEmployees() method below is the method that populates the grid in our soon to be released Silverlight demo. The method executes under Silverlight after the user types in his search criteria and hit’s the Search button. Notice that the query classes (both proxy and full server) contain their own ToXml / FromXml methods. This is because when we serialize and deserialize queries we are doing so for complex object graphs with circular references. This is more complex than what our esDataContractSerializer class is designed for.

private void PopulateEmployees()
{
    try
    {
        NorthwindClient.NorthwindClient service = new NorthwindClient.NorthwindClient();

        Proxies.EmployeesQueryProxyStub q = new Proxies.EmployeesQueryProxyStub("emp");
        q.Select(q.EmployeeID, q.FirstName, q.LastName, q.Title, q.HomePhone, q.HireDate, q.BirthDate);
        q.Where( q.FirstName.Like("%" + SearchTextBox.Text + "%") | q.LastName.Like("%" + SearchTextBox.Text + "%"));
        q.OrderBy(q.LastName.Ascending);
        q.es.Top = 5;

        // Notice we send the XML representation of the Query to the Server via the Async call “GetEmployees”
        service.GetEmployeesCompleted += GetEmployeesCompleted;
        service.GetEmployeesAsync(Proxies.EmployeesQueryProxyStub.SerializeHelper.ToXml(q));
    }
    catch (Exception exc)
    {
        Console.WriteLine(exc.StackTrace);
    }
}

The above code has called GetEmployees (a WCF service method on the server). This is what our WCF Service method on the server that receives the query looks like.

public string GetEmployees(string serializedQuery)
{
    List<Type> types = new List<Type>();
    types.Add(typeof(EmployeesQuery));

    // Deserialize our EmployeesQueryProxyStub class into our full blown server side query so we can execute it
    EmployeesQuery employeesQuery = EmployeesQuery.SerializeHelper.FromXml(
        serializedQuery, typeof(EmployeesQuery), types) as EmployeesQuery;

    EmployeesCollection employeesCollection = new EmployeesCollection();
    if (employeesCollection.Load(employeesQuery))
    {
        // Okay, we have loaded it, lets send the results back in string form
        EmployeesCollectionProxyStub proxy = new EmployeesCollectionProxyStub(employeesCollection);
        return esDataContractSerializer.ToXml(proxy);
    }

    return null;
}

Back under Silverlight in the browser our async GetEmployeesCompleted method is called, and we bind the data to the grid.

void GetEmployeesCompleted(object sender, GetEmployeesCompletedEventArgs e)
{
    try
    {
        WaitText.Visibility = Visibility.Collapsed;

        string serializedEmployees = e.Result;

        // Turn the XML into a Proxies.EmployeesCollectionProxyStub collection
        Proxies.EmployeesCollectionProxyStub employees = esDataContractSerializer.FromXml(
            serializedEmployees, typeof(Proxies.EmployeesCollectionProxyStub)) as Proxies.EmployeesCollectionProxyStub;

        // Now Databind
        EmployeesDataGrid.ItemsSource = employees.Collection;
    }
    catch (Exception exc)
    {
        Console.WriteLine(exc.StackTrace);
    }
}

This approach offers some real advantages. You can later send the serialized collection back to the server with added, updated, and deleted rows. Once on the server, deserialize it, and simply call Save on the full server side collection. This is because our proxies maintain the rowstate for you. We are still working out the kinks as we build our Silverlight application. The one problem we have right now is the Silverlight grid seems to revert back to the original data and lose our cell edits. However, this happens with the Visual Studio proxies as well. Once we get this issue resolved and are fully saving data, we will publish our Silverlight demo. If you want to use this technique, you will need to generate the client side proxies and include them in your Silverlight or WCF client application. Be sure and click the new checkbox named “Serializable Queries” on the Advanced Tab of the Generated Master template. However, as you can see from the DynamicQuery Enhancements post, we are doing more than just addressing Silverlight and WCF development.

The bug that was affecting project files has been fixed. This occurred if you edited a template instance in an existing project, and saved without visiting all of the tabs. With this fix, un-visited tabs no longer revert to their default values. There is also a Twitter toolbar button on the What’s New page so you can easily get to our Twitter page. This alpha still only supports Microsoft SQL Server.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Sunday, July 05, 2009 10:49:49 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, July 04, 2009

We have greatly improved the power of our DynamicQuery API, and there is still much more coming before our next official release goes into production. This is just a quick blog post to show some of the upcoming enhancements.

Full Expressions in OrderBy and GroupBy

This query doesn’t really make sense, but we wanted to show you what will be possible in the next release.

EmployeesQuery q = new EmployeesQuery();
q.Select(q.LastName.Substring(2, 4).ToLower());
q.OrderBy(q.LastName.Substring(2, 4).ToLower().Descending);
q.GroupBy(q.LastName.Substring(2, 4).ToLower());

EmployeesCollection coll = new EmployeesCollection();
if (coll.Load(q))
{
   string s = q.es.LastQuery;
}

The SQL Generated is as follows (and works)


SELECT SUBSTRING(LOWER([LastName]),2,4) AS 'LastName'
FROM [Employees]
GROUP BY SUBSTRING(LOWER([LastName]),2,4)
ORDER BY SUBSTRING(LOWER([LastName]),2,4) DESC

In the current production release 2009.1.0209.0, you can only use a “Column Name” in the OrderBy and GroupBy statements. In the upcoming release, you will be able use full expressions, just as you can now do in the Select statement.

Raw SQL Injection Everywhere

There may be times when you need to access some SQL feature that is not supported by our DynamicQuery API. But, now having used and fallen in love with DynamicQuery, the last thing you want to do is stop and go write a stored procedure or create a view. We have always supported the raw injection feature in our Select statement, but it will soon be available almost everywhere. The way it works is you pass in raw SQL in the form of a string surrounded by < > angle brackets. That indicates to the EntitySpaces dataproviders that you want the raw SQL passed directly to the database engine “as is”.

Here is an example query. You would never write a query like this in reality. EntitySpaces supports this simple query without having to use < > angle brackets. This is just to show all of the places that can accept the raw SQL injection technique:

EmployeesQuery q = new EmployeesQuery();
q.Select("<FirstName>", q.HireDate);
q.Where("<EmployeeID = 1>");
q.GroupBy("<FirstName>", q.HireDate);
q.OrderBy("<FirstName ASC>"); 

EmployeesCollection coll = new EmployeesCollection();
if (coll.Load(q))
{
    string s = q.es.LastQuery;
}

The SQL Generated is as follows (and works)

SELECT FirstName,[HireDate] AS 'HireDate' 
FROM [Employees] WHERE (EmployeeID = 1)
GROUP BY FirstName,[HireDate]
ORDER BY FirstName ASC

Of course, you could easily write the above query without injection, but you get the idea. The escape hatch will be available to you almost everywhere ….

EmployeesQuery q = new EmployeesQuery();
q.Select(q.FirstName);
q.Where(q.EmployeeID == 1);
q.OrderBy(q.FirstName.Ascending);
q.GroupBy(q.FirstName, q.HireDate);

Using the raw SQL injection techniques above will allow you to invoke SQL functions that we don’t support, including database vender specific SQL, and so on. Hopefully, you will almost never have to resort to writing a custom load method to invoke a stored procedure or an entirely hand written SQL statement. Of course, you can use our native API everywhere and just inject the raw SQL on the GroupBy for instance. You can mix and match to get the desired SQL.

There’s much more to come in this release …  Just last night we were serializing DynamicQuery’s from a Silverlight application and sending them to a WCF server to fetch the data… very slick. Watch for an upcoming blog post on our Silverlight demo very soon.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Saturday, July 04, 2009 11:06:11 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, June 28, 2009

We are pleased to make this new release available to current customers, there is no trial version available at this point. This release provides our DynamicQuery API built into the Client Side Proxy Stubs. The new serializable DynamicQuery’s should be Silverlight compliant as well. This release is for those who are using WebServices, Silverlight, or WCF and would like to explore our new DynamicQuery serialization feature. We will be making the source code available for our source code customers for this Alpha release as well. The release notes along with some breaking changes are at the end of this blog post (READ BEFORE INSTALLING). An upcoming Beta release will consist of much of what was requested in the Q2 Wish List forum. Just a reminder the current production release is version 2009.1.0209.0.

For more information on our new Serializable DynamicQuery’s see these two posts:

Because the two blog posts above are only in C# here is a VB.NET sample (without the proper cleanup code on the streams and such)

Private Sub QuerySerializerForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim o As New Proxies.OrdersQueryProxyStub("o")
    Dim q As New Proxies.EmployeesQueryProxyStub("emp")
    q.SelectAll()
    q.Select(q.LastName.ToLower().Substring(2, 4), o.Freight, (q.FirstName + "," + q.Address).As("Mike"))
    q.LeftJoin(o).On(q.EmployeeID = o.EmployeeID)
    q.Where(q.EmployeeID > 30)
    q.OrderBy(q.LastName.Descending)
    q.es.Top = 50

    Dim xml As String = q.Serializer.ToXml()

    Dim memoryStream As New MemoryStream(Encoding.Unicode.GetBytes(xml))

    Dim reader As XmlDictionaryReader
    reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.Unicode, New XmlDictionaryReaderQuotas(), Nothing)

    Dim types As New List(Of System.Type)
    types.Add(GetType(EmployeesQuery))
    types.Add(GetType(OrdersQuery))

    Dim emp As New EmployeesQuery()
    Dim dcs As DataContractSerializer
    dcs = emp.Serializer.GetSerializer(types)

    emp = CType(dcs.ReadObject(reader), EmployeesQuery)

    Dim coll1 As New EmployeesCollection()
    coll1.Load(emp)

End Sub

Now, in reality you shouldn’t have to do any of the manual serialization we are doing here, but of course you can if you want to. You will want to use the [KnownTypes] attribute if you are using WCF on the Server Side.

 

             RELEASE NOTES

                EntitySpaces 2009.1.0629.0 Alpha Release
                            June 29th, 2009
==================================================================================

  • This release will not run side by side with your current ES2009 installation, it will overwrite the installation even if you choose another folder. You should uninstall any prior release before installing the Alpha version.
  • The new Serializable DynamicQuery functionality requires .NET 3.5 SP1.
  • The Silverlight version of the EntitySpaces.DynamicQuery.dll is in the “C:\Program Files\EntitySpaces 2009\Runtimes\.NET 3.5\Silverlight” folder
  • There is a new checkbox on the "Advanced" tab of the "Generated Master" template named "Serializable Queries (requires .NET 3.5 SP1)" that you must check in order to use the new serializable queries.
  • When you generate your client side proxies via the "Client Side Proxy/Stub" template you will now have a client side DynamicQuery class.
  • The only data provider in this Alpha - EntitySpaces.SqlClientProvider.dll

NOTE: The breaking changes listed below should generate compile time errors, not runtime errors. Adding a reference to Entityspaces.DynamicQuery.dll to your project, and adding a "using EntitySpaces.DynamicQuery;" line to each file that has a "using EntitySpaces.Interfaces;" line should clear most of the compile errors. ("Imports EntitySpaces.DynamicQuery" for VB users.)

  • Breaking change - There is a new assembly named EntitySpaces.DynamicQuery.dll which is now a required assembly reference for all applications. This assembly should be Silverlight compliant and is the only EntitySpaces assembly needed to use the DynamicQuery's under Silverlight. The inheritance is different for the full blown server side DynamicQuery's versus the client side queries.

       Server Side DynamicQuery

          EmployeesQuery -> esEmployeesQuery -> esDynamicQuery –> esDynamicQuerySerializable

       Client Side Proxy DynamicQuery

          EmployeesQueryProxyStub -> esDynamicQuerySerializable

NOTE: The esDynamicQuery class lives in EntitySpaces.Interfaces.dll just as always, however, most of the logic behind the DynamicQuery now lives in the new esDynamicQuerySerializable class which lives in EntitySpaces.DynamicQuery.dll.

  • Breaking change - There is a minor change in the DynamicQuery API with the ".es" property. This is only for the DynamicQuery class, the Entity and Collection classes have no change in this area.

   Before the Alpha you could do this:

     EmployeesQuery query = new EmployeesQuery();
     query.es.Connection.Name = "SomeName";


   Now the connection is accessible this way ...

     EmployeesQuery query = new EmployeesQuery();
     query.es2.Connection.Name = "SomeName";

     ** Notice we use "es2" however all of the other properties are still available under the ".es" property.

   There is also a new helper when using the DynamicQuery features:

     EmployeesQuery query = new EmployeesQuery();
     query.es.Serializer.[helper methods]


   which can be used if necessary to serialize.

  • Breaking change - Many Enums that used to be in EntitySpaces.Interfaces are now in EntitySpaces.DynamicQuery

    These included:

    esQueryType
    esQuerySubOperatorType
    esOrderByDirection
    esConjunction
    esSystemType

    As well as some other internal enums.

  • Breaking change - esWhereItem was renamed to esComparison and now lives in EntitySpaces.DynamicQuery.dll. Unless you are manually creating this class which is rare you will not be affected.
  • Breaking change - esSelectItem was renamed to esExpression and now lives in EntitySpaces.DynamicQuery.dll. Unless you are manually creating this class which is rare you will not be affected.

 

We hope to have an entirely new Silverlight / WCF Demo available to coincide with and built from the upcoming Alpha release. Of course we will do a blog post on that as well. When you see it in action you will be amazed how easy it is. We still have a few issues to work out but things are moving very rapidly now. Imagine having what appears to be the full EntitySpaces API available to you on a client somewhere and only needing to have a single 52k assembly present, and it is fully Silverlight compliant as well. This is just one thing our upcoming release will provide.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Sunday, June 28, 2009 8:32:51 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, June 13, 2009
kick it on DotNetKicks.com

We have decided to use the WCF DataContract approach when serializing our enhanced DynamicQuery’s. In our upcoming alpha release, our DynamicQuery classes now live in a separate assembly that can execute on the client side along with your EntitySpaces proxies without requiring either the EntitySpaces.Core or the EntitySpaces.Interfaces assemblies. The EntitySpaces.DynamicQuery assembly (only 52k in size) is also compatible with Silverlight and can run down inside of the browser. The older .NET 2.0 serialization techniques aren’t supported under Silverlight and having this feature work under Silverlight is important to us. At this moment, the Alpha will require .NET 3.5 SP1 (if you want to use these advanced new features) as it provides the ability to serialize object graphs having circular references. Currently, our DynamicQuery API does have circular references. For instance, SelectColumns have a reference to their parent DynamicQuery object. There is a very good summary of this feature in .NET 3.5 SP1 HERE and you might want to take a look at it. More on this later however.

Take a look at this very simple query. The example code below shows a query that will ultimately do a join and is selecting columns from both the Employees and Products tables. We also call ToLower, Substring, and Sum.

ProductsQuery prod = new ProductsQuery();

EmployeesQuery emp = new EmployeesQuery();
emp.Select(emp.LastName.ToLower().Substring(2, 4), prod.QuantityPerUnit.Sum().As("Qty"), emp.FirstName);

Here is an example of what one of the internal classes in our DynamicQuery API looks like. It’s ugly because we have to use #if #else #endif syntax, but just be glad you guys never have to write such code. We need to make sure the old and the new serialization both work. Notice the DataContract and DataMember attributes. Again, these are on our internal DynamicQuery API classes. Also, don’t let the WCF term scare you, these features can be used in non WCF scenarios as well.

WCFClass

Below is some test code that we use to manually invoke the DataContractSerializer.

List<System.Type> types = new List<System.Type>();
types.Add(typeof(ProductsQuery));

DataContractSerializer dcs = new DataContractSerializer(typeof(EmployeesQuery), "Query", "es", types);
var ms = new MemoryStream();
dcs.WriteObject(ms, q);
ms.Seek(0, SeekOrigin.Begin);

StreamReader sr = new StreamReader(ms);
string xml = sr.ReadToEnd();

Now, if you want to see what the resulting XML looks like click on this LINK. Admittedly, the XML is pretty funky because it creates what are essentially pointers to objects that appear in the XML graph multiple times. However, this saves a ton of space and of course prevents an endless loop when trying to serialize circular references.

Our development test harness for this is shown below:

WCFTestHarness

Of course, when serializing and sending queries in XML over the wire, you are probably going to want to be using HTTPS so that sensitive data cannot be seen or tampered with.

What does this all mean?

Well, this means that our DynamicQuery’s can optionally be built into your proxy objects and used from the client side just as you would on the server side, only you will send your query over to the server and it will return either a proxy entity or proxy collection. Using our proxies with built in queries will feel like full blown EntitySpaces on the client side. And this will all run under Silverlight as well. Couple that with the massive improvements coming in our DynamicQuery API and that is some very cool functionality. Even if you aren’t interested in all this client side serialization stuff, you will love the enhancements coming in the DynamicQuery API. And remember, this will all work for web services too.

Before we release to production, we might be able to eliminate the circular references in our DynamicQuery object graph, however, this is not an easy thing to do. We do have a working solution via the enhancements in the .NET 3.5 SP1 release with the circular references in place.

Breaking Changes?

We are renaming quite a few internal classes. Some of them are public. For instance, esWhereItem is now called esComparison and esSelectItem is now called esExpression. Our queries are basically made up of esExpressions which are then combined with operators such as != or == to form esComparisons. The reason we needed to change these names is that they were too specific. We are going to allow you to use complex syntaxes in OrderBy, GroupBy and many other areas within the query syntax itself. Therefore, esWhereItem and esSelectItem just weren’t appropriate names. Most of you never really manually create these objects so it wont impact you at all. However, if you do, you will have to do a find/replace on these if you are manually creating them in code (which is rare).

Where are we at?

We are pushing very hard for our Alpha release to be released by the end of this month. Right now the carburetor is lying on the floor and we’re all absolutely covered in grease. However, we know how to put this back together again and when we do it’s going to be awesome. We are really excited about this release and the Q2 Wish List Forum will play, and is playing, heavily into what we deliver.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Saturday, June 13, 2009 10:44:40 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, June 11, 2009

We are implementing some major changes under the hood of our DynamicQuery API engine. We are reworking the internals while preserving the API in such a way that you will be able to use the full query syntax in OrderBy’s, GroupBy’s, in the On() statement of a join and so on. We are also making the DynamicQuery Serializable. It’s really too bad there isn’t an attribute that can make private data members serializable by the XML serialization system(s). What a major shorting coming of the .NET Framework (unless we are overlooking something).

So, basically, we are tearing the DynamicQuery apart, and when we put it back together it should be exponentially more powerful and be ready for additional features like the Having Clause and others. Like the ES2009 release, this next release should prove to be a major step forward and provide you with the additional horse power you have been asking for.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Thursday, June 11, 2009 7:39:53 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, May 28, 2009

We wanted to update you on our plans for our next ES2009 Release. On June 29th we plan to make available an Alpha version of what will eventually be our ES2009 Q3 release, it’s too late to call it our Q2 release however things are underway. We had a very productive team meeting tonight. Our Alpha will have these features:

  • A new assembly called EntitySpaces.DynamicQuery which will contain the base classes and support for our DynamicQuery API. This new assembly does not reference System.Data so it will be able to run under Silverlight inside of the browser itself.
  • The ES2009 Q3 DynamicQueries will be fully serializable and will not require EntitySpaces.Core or EntitySpaces.Interfaces on the client.
  • The ES2009 Q3 DynamicQueries can optionally be built into your Proxy/Stub classes by merely checking a checkbox which means you can send your query to the server and get back an entity or collection.

Those are the main features that will be in the Alpha. However, we have already made many fixes suggested in our Q2 Wish List Forum and will be drawing from those suggestions heavily, including major DynamicQuery API enhancements. In the ES2009 Q3 Alpha version only SQL Server will be supported. We want to make sure we have the changes right before we replicate the changes across all of our providers as we have a lot of them to maintain.

We will be doing a weekly blog post that will outline our progress and let you know what enhancements have been made and what bugs have been fixed. Our goal is to greatly expand the reach of EntitySpaces making sure it can go where ever you need to go, including greatly enhancing our DynamicQuery API. Of course, fixing any existing bugs too will be a priority.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Thursday, May 28, 2009 10:36:06 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, March 01, 2009
kick it on DotNetKicks.com     Shout it

Can you Query me now?mobile (Silverlight, WCF, Webservices, and Mobile)

EntitySpaces 2009 Q2 is going to revolutionize your ability to use the EntitySpaces 2009 architecture on the client side of any two-way conversation, whether it be a Silverlight, WCF, or a webservices conversation. In fact, you will be able to work on the client side as if the full EntitySpaces architecture was at your disposal but without actually requiring the EntitySpaces architecture be present on the client. "But how can that be?" you wonder. Continue reading and we will explain.

EntitySpaces has always had good support for mobile applications via our Compact Framework support. We even generate "smarter" proxies than the ones generated by Visual Studio for WCF or webservices scenarios. Our proxies maintain row state such as (inserted, updated, and deleted) such that all that is required is that you send the data back to the server and commit it.  But this client side proxy support is about to become much, much more powerful and can be used for non-mobile scenarios such as Silverlight, WCF, and webservices. With our enhanced proxies (especially for mobile applications where space is limited) this can prove to be a very powerful way to use EntitySpaces. We like to think of this as a sort of "Virtual EntitySpaces Mode" as it feels just like EntitySpaces only it really doesn't require the full architecture on the client side. So, let's dive into this and see how it works starting with a review of our current proxy support.
 

Our Current Client Side Proxy Functionality

The EntitySpaces Client Side proxies offer the ability to easily work with EntitySpaces on the client side of a two way conversation without requiring any of the EntitySpaces assemblies. Our proxies also track the dirty state for you so that when you send data back to the server EntitySpaces automatically knows whether to insert, update, or delete the data. This functionality is already built into the currently shipping ES2009 Q1 release. The template that you use to create the Client Side proxies is highlighted below.

ProxyStubTemplate

When you execute the "Client Side Proxy/Stub" template there are currently two classes generated for you, the Collection and Entity class. Shown below are the proxy stub classes that were generated by the "Client Side Proxy/Stub" template for the Microsoft Northwind Suppliers table. Notice that the classes do not inherit from any base classes nor do they require any of the EntitySpaces assemblies. Also, in the SuppliersProxyStub (entity) class notice the esRowState property. This is the property that EntitySpaces uses to determine the state of the entity (inserted, updated, or deleted) and the proxy is smart enough to set this property for you based on the actions you take (you do not have to worry about setting it). These two classes are extremely small and lightweight in size.

proxystub1

With these two classes you work with data on the client side of a conversation without EntitySpaces being present, but something is missing, a feature that hooks most EntitySpaces developer once they start using it.

New Functionality Coming in ES2009 Q2

In our ES2009 Q2 release the Client Side template will now generate a new, optional, third class, the "QueryProxyStub" class. Yes, you guessed it, the full EntitySpaces DynamicQuery API now available on the client side of a two-way conversation. Take a look at the SuppliesQueryProxyStub class below. This class is just like the DynamicQuery classes you are accustomed to using already only it inherits from a new class named esDynamicQuerySerializable. If you take a close look at the methods in the esDynamicQuerySerializable class you will notice that there are no methods to load or execute the query itself (more on this later). This query can only be created, defined, and then serialized back to the server (a very cool way to write a Silverlight application). If you have never seen how powerful our DynamicQuery API is check out our Showcase post HERE.

proxystub2

Now, imagine that you're on the client side of a WCF conversation or even running down inside the browser in a Silverlight application and you need to query your Supplier table for data. No problem, here is how you would accomplish that task with the new proxy query class.

SuppliersQueryProxyStub sQuery = new SuppliersQueryProxyStub ();
sQuery.Select(sQuery.SupplierID, sQuery.Region);
sQuery.Where(sQuery.Country == "Spain");

Notice that we do not call sQuery.Load(). This is because the esDynamicQuerySerializable has no way to actually load data, it represents the query only, the ability to load it (or execute it) exists on the server side of the conversation. Also, the full join syntax is available although it is not shown above in the query. The proxy queries are fully serializable which is the key to how it works. At a very high level this is how you would fetch data from the server, imagine a method like this:

public SuppliersCollectionProxyStub FetchSupplers(SuppliersQueryProxyStub query)

You would transmit the proxy stub query to the server, where it will be deserialized, assigned to a full server query object, executed, and then the resulting proxy stub collection would be returned. The code will look very much like this.

public SuppliersCollectionProxyStub FetchSupplers(SuppliersQueryProxyStub query)
{
    SuppliersCollection coll = new SuppliersCollection();
    coll.Query = query as esDynamicQuerySerializable;
    coll.Query.Load();

    // more code below ...
}

Notice how we are able to merely assign our SuppliersQueryProxyStub object to the full blown SuppliersCollection's query object and then execute it. Could it be any easier?

EntitiySpaces.DynamicQuery - A New Assembly

Just where does this esDynamicQuerySerializable class that our SuppliersQueryProxyStub inhertis from live? The answer is a new assembly that will ship with ES2009 Q2 named EntitySpaces.DynamicQuery.dll. This is very tiny (less that 50k) assembly that only references System.Core and System.XML and is fully Silverlight 2.0 compliant. It does not link with EntitySpaces.Core or EntitySpaces.Interfaces. However, even better we are not maintaining two separate DynamicQuery API's. This new assembly and class is used on the server side as well, which means this new assembly is required now for EntitySpaces applications. Look at the diagram below which shows the hierarchy of a normal DynamicQuery class as generated by the ES2009 Q2 Generated Master template. This preserves your current API.

proxystub3

Notice the the original base class esDynamicQuery is still there, however, it now inherits from the esDynamicQuerySerializable class. In order to run under Silverlight our client side DynamicQuery assembly could not reference the System.Data namespace, so we have separated the original esDynamicQuery into the two classes you see above.

What Does it All Mean?

Our new enhanced client side proxies will allow you to have a "Virtual EntitySpaces Architecture" running almost anywhere including mobile devices, Silverlight applications, WCF scenarios, and webservices. It will act and feel just like EntitySpaces Of course, we can already run in all of these environments but with ES2009 Q2 and the addition of the DynamicQuery proxy and the massive DynamicQuery API enhancements that are also coming you will truly be blown away by the productivity and reach of the EntitySpaces Architecture. The only thing that is required on the client to make this all possible is the tiny EntitySpaces.DynamicQuery assembly (less than 50k) which is completely Silverlight compliant. There are other enhancements that will be made to the proxies but we will keep them small and lightweight.

There are also a few technical issues we must solve yet, though most have been worked out. For example, where do the extra properties go when you bring them back via a join? In the full server side classes this is handled gracefully, and we make those properties appear as if there are in your strongly typed entities via sophisticated binding support. How do we do this on the client side? These are a few of the issues we must solve yet.

We find this new support terribly exciting and it presents almost boundless usage scenarios. Especially when you factor in the enhancements we are making to DynamicQuery API itself, but that is the topic for another post. And keep those comments coming in our ES2009 Wish List forum, we are listening and will implement a lot of your requested features.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Sunday, March 01, 2009 1:31:36 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Wednesday, January 07, 2009

This is not an example how to use EntitySpaces. Most everything shown below can be done through our DynamicQuery API which is the preferred way. For instance, the GetMaxSalary() example shown in the EmployeesCollection class below could be done via our DynamicQuery like this:

EmployeesQuery query = new EmployeesQuery();
query.Select(query.Salary.Max());
int maxSalary = (int)query.ExecuteScalar();
And the CustomLoad() load method shown in the EmployeesCollection class below could be done via our DynamicQuery like this: 
EmployeesCollection coll = new EmployeesCollection();
coll.Query.Where(coll.Query.LastName.Like("g%"));
if(coll.Query.Load())
{
    // Then we loaded at least one record
}

So, when you look at the class below remember this is merely to demonstrate to you some of the lower level support functions that you have at your disposal. The idea being, of course, even though you are using an ORM system generated via our ES2009 code generator you are not cut off from the low level ADO.NET API when you need to hug the metal.

public partial class EmployeesCollection : esEmployeesCollection
{
    public bool CustomLoad(string partialName)
    {
        // This populates the EmployeesCollection itself
        return this.Load(esQueryType.Text, "SELECT * FROM EMPLOYEES WHERE LastName Like {0}", partialName);
    }

    public DataSet GetDataSet(int someParameter)
    {
        // We hate DataSets ;)
        return this.FillDataSet(esQueryType.StoredProcedure, "TestProc", someParameter);
    }

    public DataTable GetDataTable(int someParameter)
    {
        // We hate DataTables ;)
        return this.FillDataTable(esQueryType.StoredProcedure, "TestProc", someParameter);
    }

    public IDataReader GetReader(string partialName)
    {
        // We hate DataReaders ;)
        return this.ExecuteReader(esQueryType.Text, "SELECT * FROM EMPLOYEES WHERE LastName Like {0}", partialName);
    }

    public int GetMaxSalary()
    {
        return (int)this.ExecuteScalar(esQueryType.StoredProcedure, "procGetMaxSalary");
    }
}


Of course, we don't really hate DataSets, DataTables, or DataReaders. If you are an EntitySpaces user then you know that using our DynamicQuery API is the way to go. However, if there is something you need that is not available in our DynamicQuery API you have full access to the underlying power of ADO.NET.

There is also a utility class called esUtility that will allow you to access this lower level API without adding custom methods to your EntitySpaces classes. This can be useful when what you need to do doesn't really belong to a particular entity. Here is an example of using the esUtility class.

esUtility util = new esUtility();
IDataReader reader = util.ExecuteReader(esQueryType.Text, "SELECT * FROM EMPLOYEES WHERE LastName Like {0}", "g%");

One thing to note is that you never use decorators on your parameters such as ? or @ or : (depending on your database). The EntitySpaces Data Providers do this for you. For instance, notice in the sample code below that we do not set the parameter name to "@Salary" rather we just use "Salary". This allows you to access stored procedures and still have a database independent application as the EntitySpaces Data Provider will "gussy up" the parameters with the proper decorator. In fact,  you really don't have to use the syntax below unless you need to provide extra information such as parameter direction or perhaps the precision or scale of a decimal for some reason. Otherwise you can just use the {0}, {1} syntax as shown above in the GetReader() method. Even when using the {0} syntax EntitySpaces will create a true parameter for you to ensure that no SQL injection attacks are successful.

esParameters parameters = new esParameters();
esParameter param = new esParameter("Salary", null, esParameterDirection.Output);
parameters.Add(param);

esUtility util = new esUtility();
IDataReader reader = util.ExecuteReader(esQueryType.StoredProcedure, "GetMaxSalary", parameters);

While were at it here's another data access tip. This tip allows you to trick your table based collection (via the DynamicQuery) to query against a view. Of course, you can generate entities from a view if you like but if you don't really want the additional classes you can use this technique instead. Notice how we set the QuerySource below.

EmployeesCollection coll = new EmployeesCollection();
coll.Query.es.QuerySource = "MyView"; // <== Select against this view
coll.Query.Select(coll.Query.LastName, coll.Query.FirstName);
coll.Query.Where(coll.Query.Salary > 50000);
coll.Query.Load();

This can be very useful since you can still commit this data back to the Employee table provided that you also brought back the primary key, of course. And remember, these are tricks, not necessarily how to use EntitySpaces. You can easily use our DynamicQuery API to build a join on the fly to that would accomplish the same thing as the view above.

In summary we have worked very hard to expose all of the underlying power of ADO.NET and yet you never have to pull in SqlClient, OracleClient or any other ADO.NET provider. Better still you can invoke stored procedures and not lose database independence if that is what you are after. We hope you have learned a thing or two from this post.

EntitySpaces

From Mobile Devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with Medium Trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.


EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Wednesday, January 07, 2009 11:37:43 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Monday, August 18, 2008

We thought we'd tell you about two nice enhancements to our DynamicQuery API. We added two new methods to the esDynamicQuery class, ExecuteScalar and ExecuteReader. These will be available in our next ES2008 maintenance release when it comes out.

ExecuteScalar:

This query simply fetches the total table count. Of course, I could have used a Where clause to reduce it to a certain set of records.

EmployeesQuery query = new EmployeesQuery();
query.es.CountAll = true;
int count = (int)query.ExecuteScalar();

ExecuteReader:

This query selects the FirstName and LastName columns where the LastName is like "Gri%" and then gets an IDataReader on the result set.

EmployeesQuery query = new EmployeesQuery();
query.Select(query.FirstName, query.LastName);
query.Where(query.LastName.Like("Gri%"));

using (IDataReader reader = query.ExecuteReader())
{
    while (reader.Read())
    {
        string s = reader.GetString(0);
    }
}

Notice that neither of these approaches is used to populate a collection or an entity. This is similar to the already existing Query.LoadDataTable() method.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Monday, August 18, 2008 8:30:58 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, April 13, 2008
kick it on DotNetKicks.com

beach


Vacation

If you noticed that I wasn't around much on the forums this past week you weren't imagining things. I was on vacation in Palm Beach Gardens, Florida. It's truly paradise on earth. We went to Juno Beach almost every day (don't let the Jones Beach shirt fool you). I was there with my wife and three children and we played in the waves all week, it was awesome. Maybe I'll post some other photos later. I have to admit it's a little depressing to be back in Indianapolis and it's only 39 degree's here (it was in the mid 80's all week in Florida).

During the evenings I was able to read the new LINQ in Action book published by Manning. I was particularly interested in the LINQ to SQL functionality and how it could be applied to EntitySpaces. Well, it's been less than 24 hours since I've been home and I already have LINQ to SQL working with EntitySpaces. The LINQ in Action book is pretty good as a LINQ reference but it really kind of ticked me off otherwise. The strawman it setup in order to tear down was really blatant. I think I could take nearly all of the the supposed samples it uses to show how much better LINQ is over ADO.NET and provide appropriate samples using EntitySpaces and it would be far more intuitive. I might just do that later to make a point.

Okay, enough ranting, let's focus on using EntitySpaces with LINQ to SQL (for Microsoft SQL Server only so far).

EntitySpaces and LINQ to SQL

Adding support to EntitySpaces for LINQ to SQL was pretty easy. I added [Table] and [Column] attributes from the System.Data.Linq.Mapping namespace to my "generated" Employee entity like so:


[Table(Name="Employee")]
public partial class Employee : esEmployee
{
    [Column(IsPrimaryKey = true, CanBeNull = false)]
    public override int? EmployeeID
    {
        get { return base.EmployeeID;  }
        set { base.EmployeeID = value; }
    }

    [Column]
    public override string LastName
    {
        get { return base.LastName;  }
        set { base.LastName = value; }
    }

    // more properties here ...
}

I had to make pass through's for the properties however. Recall that the properties are in the generated esEmployee class not the generated Employee class and the esEmployee class is abstract. LINQ cannot instantiate the abstract esEmployee class and it appears that the [Table] and [Column] attributes must be on the same physical class (no inheritance allowed). So I made overrides of the properties in my Employee class, applied the attributes, and I was ready to test. For more information on the inheritance LINQ limitation see this MSDN forum post.

After making the above changes it was time to test it and see if worked. Below is my test code.

DataContext dataContext = new DataContext("User ID=sa;password=; ... ");

var employees = dataContext.GetTable<Employee>();
var query = from employee in employees where employee.Age < 50 select employee;

foreach (Employee emp in query)
{
    Console.WriteLine(emp.Age.ToString());
}

As I suspected and hoped, it worked. However, semantically this is a little different that using our DynamicQuery API. I didn't get back an EntitySpaces EmployeesCollection class. Instead I was handed a System.Linq.IQueryable<BusinessObjects.Employee> interface which I could then use to enumerate over the individual Employee objects. However, these were my true EntitySpaces objects which was kind of cool. This is all still exploratory and is slower than using the EntitySpaces DynamicQuery API but still offers valuable functionality. We're pushing hard on the next ES2008 beta and as time allows we will sneak in some of these cool new features as time allows. My guess is this will make the first release of ES2008.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Sunday, April 13, 2008 12:32:08 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, March 22, 2008

A Quick "Cast" Sample

kick it on DotNetKicks.com

The casting logic is now in-place for the EntitySpaces 2008 March 30 Beta release. Let's look at a few quick examples, so you can get a feel for how this new feature works. These examples are not real world scenarios, and were chosen to merely demonstrate the syntax.

EmployeeCollection coll = new EmployeeCollection();
EmployeeQuery q = coll.Query;

q.Select
(
    (
        (q.LastName + ", " + q.FirstName).Trim() + " [" + (esString)q.Age + "]"
    )
    .ToUpper().As("FirstName")
);

if (coll.Query.Load())
{
    foreach (Employee emp in coll)
    {
        string fn = emp.FirstName;
    }
}

The sample above is a little over the top, but we wanted to show you some of the features. Notice that we Trim the results of ("LastName+ ", " + FirstName") by placing parenthesis around it, and then using Trim. However, we're not finished yet. We then continue by concatenating the Age. We cast Age into a string using the (esString) cast operator. You can use our natural language syntax throughout the EntitySpaces DynamicQuery API. 

The resulting values for FirstName would be as follows:

SMITH, JOHN [30]
DOE, JANE [20]

The SQL generated for the Query above would be as follows:

SELECT UPPER((((LTRIM(RTRIM((([LastName]+', ')+[FirstName])))+' [')+CAST([Age] AS nvarchar))+']')) AS 'FirstName'  FROM [Employee]

If you match-up the color coding from the EntitySpaces DynamicQuery to the resulting SQL, you can see that the (esString) resulted in a call to Cast(). Note how at various points we were able to group things with parenthesis to apply further processing, for example, Trim and ToUpper. Finally, we end the query by providing our virtual column with an alias. We even aliased it back to our FirstName column, so we could access it directly with a property instead of using GetColumn().

Supported Cast Operators

The cast operators supported are as follows:

  • esBoolean
  • esByte
  • esChar
  • esDateTime
  • esDecimal
  • esDouble
  • esGuid
  • esInt16
  • esInt32
  • esInt64
  • esSingle
  • esString

More Advanced Casting

In cases where you need a little more control, you can use the Cast() method in the query explicitly. There are three methods available.

  1. Cast(esCastType castType)                                       - Really offers nothing over the inline casting shown above
  2. Cast(esCastType castType, int length)                     - useful when casting strings
  3. Cast(esCastType castType, int precision, int scale) - useful for numeric/decimal types

Forgive us, if these samples aren't quite real world samples:

Employee emp = new Employee();
emp.Query.Select(emp.Query.Age.Cast(esCastType.Decimal, 8, 4).As("CastColumn"));
emp.Query.es.Top = 1;

if(emp.Query.Load())
{

}

This results in:

SELECT  TOP 1 CAST([Age] AS decimal(8,4)) AS 'CastColumn'  FROM [Employee]

If you didn't need to control the precision and scale, you could just use the syntax shown below:

Employee emp = new Employee();
emp.Query.Select((esDecimal)emp.Query.Age.As("CastColumn"));
emp.Query.es.Top = 1;

if(emp.Query.Load())
{

}

This results in:

SELECT  TOP 1 CAST([Age] AS decimal) AS 'CastColumn'  FROM [Employee]

Summary

Our new casting support, combined with our new SubQuery support, should add to the horsepower already provided by EntitySpaces 2007. EntitySpaces 2008 will give you a real boost when it comes to writing your EntitySpaces applications. EntitySpaces 2008 extends the DynamicQuery API significantly. All of these features are supported for all of the EntitySpaces databases.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Saturday, March 22, 2008 6:10:33 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, March 02, 2008

kick it on DotNetKicks.com

EntitySpaces, LLC will be delivering substantial SubQuery horsepower in its 2008 release. The EntitySpaces DynamicQuery API (just one of the features of using EntitySpaces) has proven to be a very powerful tool for .NET developers. Not only is the syntax very intuitive and similar to SQL itself but it is also database independent. Even more importantly, the EntitySpaces DynamicQuery API is fully supported on the Compact Framework, Mono, and in ASP.NET Medium Trust Mode. It is also supported for Microsoft SQL and SQL CE, Oracle, MySQL, PostgreSQL, VistaDB, and Microsoft Access and will run on the .NET 2.0 Framework and higher.

SelectAllExcept()

SelectAllExcept() is not really a SubQuery, just a convenient enhancement that allows you to select all except one or more listed columns.

EmployeeCollection coll = new EmployeeCollection();
coll.Query.SelectAllExcept(
    coll.Query.EmployeeID,
    coll.Query.FirstName);
coll.Query.Load();

Results:

SELECT [LastName],[Supervisor],[Age]  
FROM [ForeignKeyTest].[dbo].[Employee]

Select SubQuery

A SubQuery in a Select clause must return a single value.

OrderQuery orders = new OrderQuery("o");
OrderItemQuery details = new OrderItemQuery("oi");

orders.Select
(
    orders.OrderID,
    orders.OrderDate,
    details.Select(
        details.UnitPrice.Max())
        .Where(orders.OrderID == details.OrderID).As("MaxUnitPrice")
);

OrderCollection collection = new OrderCollection();
collection.Load(orders);

Results:

SELECT o.[OrderID],o.[OrderDate], 
    (SELECT MAX(oi.[UnitPrice]) AS 'UnitPrice'  
    FROM [ForeignKeyTest].[dbo].[OrderItem] oi 
    WHERE o.[OrderID] = oi.[OrderID]) AS MaxUnitPrice  
FROM [ForeignKeyTest].[dbo].[Order] o

This is the same as the query above, but returns all columns in the Order table, instead of just OrderID and OrderDate. Notice that the Select clause contains orders, not orders.*. The SQL produced will use the supplied alias o.*.

OrderQuery orders = new OrderQuery("o");
OrderItemQuery details = new OrderItemQuery("oi");

orders.Select
(
    orders,
    details.Select(
        details.UnitPrice.Max())
        .Where(orders.OrderID == details.OrderID).As("MaxUnitPrice")
);

OrderCollection collection = new OrderCollection();
collection.Load(orders);

Results:

SELECT o.*, 
    (SELECT MAX(oi.[UnitPrice]) AS 'UnitPrice'  
    FROM [ForeignKeyTest].[dbo].[OrderItem] oi 
    WHERE o.[OrderID] = oi.[OrderID]) AS MaxUnitPrice  
FROM [ForeignKeyTest].[dbo].[Order] o

From SubQuery

An aggregate requires a GROUP BY for each column in the SELECT that is not an aggregate. Sometimes you wish to include columns in your result set that you do not wish to group by. One way to accomplish this is by using a SubQuery in the From clause that contains the aggregate the way you want it grouped. The outer query contains the results of the aggregate, plus any additional columns.

If you use a SubQuery in a From clause, you must give the From clause its own alias (shown below as "sub"). In the outer query, to refer to an aliased element in the From SubQuery, use the inline raw SQL technique to qualify the aggregate's alias with the From clause alias, i.e., "<sub.OrderTotal>".

OrderQuery oq = new OrderQuery("o");
OrderItemQuery oiq = new OrderItemQuery("oi");

oq.Select(oq.CustID, oq.OrderDate, "<sub.OrderTotal>");
oq.From
    (
        oiq.Select(oiq.OrderID,
            (oiq.UnitPrice * oiq.Quantity).Sum().As("OrderTotal"))
            .GroupBy(oiq.OrderID)
    ).As("sub");
oq.InnerJoin(oq).On(oq.OrderID == oiq.OrderID);

OrderCollection collection = new OrderCollection();
collection.Load(oq);

Results:

SELECT o.[CustID],o.[OrderDate],sub.OrderTotal  
FROM (
    SELECT oi.[OrderID],
    SUM((oi.[UnitPrice]*oi.[Quantity])) AS 'OrderTotal'  
    FROM [ForeignKeyTest].[dbo].[OrderItem] oi 
    GROUP BY oi.[OrderID]) AS sub 
INNER JOIN [ForeignKeyTest].[dbo].[Order] o 
ON o.[OrderID] = sub.[OrderID]

Where SubQuery

In and NotIn are two of the most common operators used in a Where SubQuery. The following produces a result set containing Territories that an Employee is not associated with.

// SubQuery of Territories that Employee 1 is assigned to.
EmployeeTerritoryQuery etq = new EmployeeTerritoryQuery("et");
etq.Select(etq.TerrID);
etq.Where(etq.EmpID == 1);

// Territories that Employee 1 is not assigned to.
TerritoryQuery tq = new TerritoryQuery("t");
tq.Select(tq.Description);
tq.Where(tq.TerritoryID.NotIn(etq));

TerritoryCollection collection = new TerritoryCollection();
collection.Load(tq);

Results:

SELECT t.[Description]  
FROM [ForeignKeyTest].[dbo].[Territory] t 
WHERE t.[TerritoryID] NOT IN (
    SELECT et.[TerrID]  
    FROM [ForeignKeyTest].[dbo].[EmployeeTerritory] et 
    WHERE et.[EmpID] = @EmpID1) 

Exists evaluates to true, if the SubQuery returns a result set.

// SubQuery of Employees with a null Supervisor column.
EmployeeQuery sq = new EmployeeQuery("s");
sq.es.Distinct = true;
sq.Select(sq.EmployeeID);
sq.Where(sq.Supervisor.IsNull());

// If even one employee has a null supervisor,
// i.e., the above query has a result set,
// then run a list of all employees.
EmployeeQuery eq = new EmployeeQuery("e");
eq.Select(eq.EmployeeID, eq.Supervisor);
eq.Where(eq.Exists(sq));

EmployeeCollection collection = new EmployeeCollection();
collection.Load(eq);

Results:

SELECT e.[EmployeeID],e.[Supervisor]  
FROM [ForeignKeyTest].[dbo].[Employee] e 
WHERE EXISTS (
    SELECT  DISTINCT s.[EmployeeID]  
    FROM [ForeignKeyTest].[dbo].[Employee] s 
    WHERE s.[Supervisor] IS NULL) 

Join(query).On(SubQuery)

SubQueries cannot be used directly within a Join(SubQuery) clause, but they can be used within a Join(query).On(SubQuery) clause.

// Query for the Join
OrderItemQuery oiq = new OrderItemQuery("oi");

// SubQuery of OrderItems with a discount
OrderItemQuery oisq = new OrderItemQuery("ois");
oisq.es.Distinct = true;
oisq.Select(oisq.Discount);
oisq.Where(oisq.Discount > 0);

// Orders with discounted items
OrderQuery oq = new OrderQuery("o");
oq.Select(oq.OrderID, oiq.Discount);
oq.InnerJoin(oiq).On(oq.OrderID == oiq.OrderID &
    oiq.Discount.In(oisq));

OrderCollection collection = new OrderCollection();
collection.Load(oq);

Results:

SELECT o.[OrderID],oi.[Discount]  
FROM [ForeignKeyTest].[dbo].[Order] o 
INNER JOIN [ForeignKeyTest].[dbo].[OrderItem] oi 
ON (o.[OrderID] = oi.[OrderID] AND oi.[Discount] IN  (
    SELECT  DISTINCT ois.[Discount]  
    FROM [ForeignKeyTest].[dbo].[OrderItem] ois 
    WHERE ois.[Discount] > @Discount1))

Correlated SubQuery

A correlated SubQuery is where the inner query relies on an element of the outer query. The inner select cannot run on its own. Below, the inner pq query uses the outer query's oiq.ProductID in the Where() clause.

OrderItemQuery oiq = new OrderItemQuery("oi");
ProductQuery pq = new ProductQuery("p");

oiq.Select(
    oiq.OrderID,
    (oiq.Quantity * oiq.UnitPrice).Sum().As("Total")
);
oiq.Where(oiq.ProductID
    .In(
        pq.Select(pq.ProductID)
        .Where(oiq.ProductID == pq.ProductID)
    )
);
oiq.GroupBy(oiq.OrderID);

OrderItemCollection collection = new OrderItemCollection();
collection.Load(oiq);

Results:

SELECT oi.[OrderID],SUM((oi.[Quantity]*oi.[UnitPrice])) AS 'Total'  
FROM [ForeignKeyTest].[dbo].[OrderItem] oi 
WHERE oi.[ProductID] IN (
    SELECT p.[ProductID]  
    FROM [ForeignKeyTest].[dbo].[Product] p 
    WHERE oi.[ProductID] = p.[ProductID])  
GROUP BY oi.[OrderID]

Nested SubQuery

EntitySpaces supports nesting of SubQueries. Each database vendor has their own limits on just how deep the nesting can go. EntitySpaces supports two different syntax approaches to nested SubQueries.

Traditional SQL-style syntax is most useful if you already have a query designed using standard SQL, and are just converting it to a DynamicQuery.

OrderQuery oq = new OrderQuery("o");
CustomerQuery cq = new CustomerQuery("c");
EmployeeQuery eq = new EmployeeQuery("e");

// OrderID and CustID for customers who ordered on the same date
// a customer was added, and have a manager whose 
// last name starts with 'S'.
oq.Select(
    oq.OrderID,
    oq.CustID
);
oq.Where(oq.OrderDate
    .In(
        cq.Select(cq.DateAdded)
        .Where(cq.Manager.In(
            eq.Select(eq.EmployeeID)
            .Where(eq.LastName.Like("S%"))
            )
        )
    )
);

OrderCollection collection = new OrderCollection();
collection.Load(oq);

Results:

SELECT o.[OrderID],o.[CustID]  
FROM [ForeignKeyTest].[dbo].[Order] o 
WHERE o.[OrderDate] IN (
    SELECT c.[DateAdded]  
    FROM [ForeignKeyTest].[dbo].[Customer] c 
    WHERE c.[Manager] IN (
        SELECT e.[EmployeeID]  
        FROM [ForeignKeyTest].[dbo].[Employee] e 
        WHERE e.[LastName] LIKE @LastName1) )

Nesting by query instance name can be easier to understand and construct, if you are starting from scratch, and have no pre-existing SQL to go by. The trick is to start with the inner-most SubQuery and work your way out. The query below produces the same results as the traditional SQL-style query above. The instance names are color coded to emphasize how they are nested.

// Employees whose LastName begins with 'S'.
EmployeeQuery eq = new EmployeeQuery("e");
eq.Select(eq.EmployeeID);
eq.Where(eq.LastName.Like("S%"));

// DateAdded for Customers whose Managers are in the
// EmployeeQuery above.
CustomerQuery cq = new CustomerQuery("c");
cq.Select(cq.DateAdded);
cq.Where(cq.Manager.In(eq));

// OrderID and CustID where the OrderDate is in the
// CustomerQuery above.
OrderQuery oq = new OrderQuery("o");
oq.Select(
    oq.OrderID,
    oq.CustID
);
oq.Where(oq.OrderDate.In(cq));

OrderCollection collection = new OrderCollection();
collection.Load(oq);

Results:

SELECT o.[OrderID],o.[CustID]  
FROM [ForeignKeyTest].[dbo].[Order] o 
WHERE o.[OrderDate] IN (
    SELECT c.[DateAdded]  
    FROM [ForeignKeyTest].[dbo].[Customer] c 
    WHERE c.[Manager] IN (
        SELECT e.[EmployeeID]  
        FROM [ForeignKeyTest].[dbo].[Employee] e 
        WHERE e.[LastName] LIKE @LastName1) )

Any, All, and Some

ANY, ALL, and SOME are SubQuery qualifiers. They precede the SubQuery they apply to. For most databases, ANY and SOME are synonymous. Usually, if you use an operator (>, >=, =, <, <=) in a Where clause against a SubQuery, then the SubQuery must return a single value. By applying a qualifier to the SubQuery, you can use operators against SubQueries that return multiple results.

Notice, below, that the ALL qualifier is set to true for the SubQuery with "cq.es.All = true;".

// DateAdded for Customers whose Manager  = 3
CustomerQuery cq = new CustomerQuery("c");
cq.es.All = true;
cq.Select(cq.DateAdded);
cq.Where(cq.Manager == 3);

// OrderID and CustID where the OrderDate is 
// less than all of the dates in the CustomerQuery above.
OrderQuery oq = new OrderQuery("o");
oq.Select(
    oq.OrderID,
    oq.CustID
);
oq.Where(oq.OrderDate < cq);

OrderCollection collection = new OrderCollection();
collection.Load(oq);

Results:

SELECT o.[OrderID],o.[CustID]  
FROM [ForeignKeyTest].[dbo].[Order] o 
WHERE o.[OrderDate] < ALL (
    SELECT c.[DateAdded]  
    FROM [ForeignKeyTest].[dbo].[Customer] c 
    WHERE c.[Manager] = @Manager1)

Below, is a nested SubQuery. The ANY qualifier is set to true for the middle SubQuery with "cq.es.Any = true;".

// Employees whose LastName begins with 'S'.
EmployeeQuery eq = new EmployeeQuery("e");
eq.Select(eq.EmployeeID);
eq.Where(eq.LastName.Like("S%"));

// DateAdded for Customers whose Managers are in the
// EmployeeQuery above.
CustomerQuery cq = new CustomerQuery("c");
cq.es.Any = true;
cq.Select(cq.DateAdded);
cq.Where(cq.Manager.In(eq));

// OrderID and CustID where the OrderDate is 
// less than any one of the dates in the CustomerQuery above.
OrderQuery oq = new OrderQuery("o");
oq.Select(
    oq.OrderID,
    oq.CustID
);
oq.Where(oq.OrderDate < cq);

OrderCollection collection = new OrderCollection();
collection.Load(oq);

Results:

SELECT o.[OrderID],o.[CustID]  
FROM [ForeignKeyTest].[dbo].[Order] o 
WHERE o.[OrderDate] < ANY (
    SELECT c.[DateAdded]  
    FROM [ForeignKeyTest].[dbo].[Customer] c 
    WHERE c.[Manager] IN (
        SELECT e.[EmployeeID]  
        FROM [ForeignKeyTest].[dbo].[Employee] e 
        WHERE e.[LastName] LIKE @LastName1) )

Some Final Thoughts

The examples given above were designed to demonstrate (and test) usage in a variety of settings. They are not necessarily the simplest, or most efficient, way to achieve the desired result set. Think of them as an API usage guide, not as design guidelines. Most SubQueries can be re-written as Joins, and most Joins can be re-written as SubQueries. If, while coding, you are having trouble conceptualizing one approach, then try the other.

Technically, a JOIN's ON clause can take almost any where_condition, and EntitySpaces supports many of these, including SubQueries. But, we agree with most authorities on the subject, that the ON clause should be reserved for the conditions that relate the two tables. All other conditional statements should be placed in a WHERE clause. Typically, the ON clause only contains a column from each table and a comparison operator.

For example, take the Join(query).On(SubQuery) example above. The much simpler query below returns the same result set. Its Where() clause not only simplifies the On() clause, but eliminates the SubQuery completely.

// Query for the Join
OrderItemQuery oiq = new OrderItemQuery("oi");

// Orders with discounted items
OrderQuery oq = new OrderQuery("o");
oq.Select(oq.OrderID, oiq.Discount);
oq.InnerJoin(oiq).On(oq.OrderID == oiq.OrderID);
oq.Where(oiq.Discount > 0);

OrderCollection collection = new OrderCollection();
collection.Load(oq);

Now might be a good time to point out that we are not in the complex query creation business. If you post a bunch of SQL, and ask, "How do I do this in EntitySpaces?", you may, or may not, get much of a response. The Peer to Peer forums are your best bet for that kind of post. On the other hand, if you post an EntitySpaces DynamicQuery that is throwing an exception, or producing inaccurate results, you will find us eager to resolve the issue.

We are going to need your help, however. As always, post the database and EntitySpaces version, the relevant code, the exception (if any), and the stack trace. We do not have your database schema, so if you can narrow down the issue using Northwind or pubs, that is a tremendous help. Posting obj.Query.es.LastQuery can provide valuable clues.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, a Mono application, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Sunday, March 02, 2008 10:40:32 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, February 07, 2008
kick it on DotNetKicks.com

We're busy working on EntitySpaces 2008 (ES2008) and thought we would demonstrate to you how subqueries will work. If you are familiar with our Join syntax then subqueries will feel like a perfect extension. The EntitySpaces 2008 architecture allows subqueries on the Select, the Where, the From, and the Join statement. Before we look at subqueries take a moment to review how our join syntax works. The EntitySpaces DynamicQuery API has proven to be very popular, so much so that other architectures are following suit.

EntitySpaces Join Syntax Review

Notice that we create three query objects and then relate them through InnerJoins and finally ask the CustomerCollection to load the query.

CustomerQuery cust = new CustomerQuery ("c");
OrderQuery order = new OrderQuery ("o");
OrderItemQuery item = new OrderItemQuery ("oi");

cust.Select(cust.CustomerName, (item.Quantity * item.UnitPrice).Sum().As("TotalSales"));
cust.InnerJoin(order).On(order.CustID == cust.CustomerID);
cust.InnerJoin(item).On(item.OrderID == order.OrderID);
cust.GroupBy(cust.CustomerName);
cust.OrderBy("TotalSales", esOrderByDirection.Descending);

CustomerCollection coll = new CustomerCollection ();
coll.Load(cust);

Pretty sweet and that is supported in ES2007 which is shipping now. But we're just getting started. Now let's look at some subquery samples.

EntitySpaces SubQuery in the Select Statement

This subquery determines the Maximum Unit Price for each order in the system.

OrdersQuery orders = new OrdersQuery("orders");
OrderDetailsQuery details = new OrderDetailsQuery("details");

orders.Select
(
    orders.OrderID,
    orders.OrderDate,
    details.Select(details.UnitPrice.Max()).Where(orders.OrderID == details.OrderID).As("MaxUnitPrice")
);
OrdersCollection coll = new OrdersCollection();
coll.Load(orders);

The resulting SQL generated by our SqlClientProvider is as follows.

SELECT orders.[OrderID],orders.[OrderDate],
(
    SELECT MAX(details.[UnitPrice]) AS 'UnitPrice' 
    FROM [Northwind].[dbo].[Order Details] details
    WHERE orders.[OrderID] = details.[OrderID]
) AS MaxUnitPrice 
FROM [Northwind].[dbo].[Orders] orders

The resulting data is as follows:

OrderID     OrderDate               MaxUnitPrice
----------- ----------------------- --------------
10248       1996-07-04 00:00:00.000    34.80
10249       1996-07-05 00:00:00.000    42.40
10250       1996-07-08 00:00:00.000    42.40
10251       1996-07-08 00:00:00.000    16.80
10252       1996-07-09 00:00:00.000    64.80
10253       1996-07-10 00:00:00.000    16.00
10254       1996-07-11 00:00:00.000    19.20
10255       1996-07-12 00:00:00.000    44.00
10256       1996-07-15 00:00:00.000    26.20

EntitySpaces SubQuery in the From Clause

Now let's look at using a subquery used in the From clause which returns the average freight per company.

OrdersQuery o = new OrdersQuery("o");

CustomersQuery c = new CustomersQuery("c");
c.Select(c.CompanyName, c.Country, o.Freight);
c.From
    (
        o.Select(o.CustomerID, o.Freight.Avg()).GroupBy(o.CustomerID)
    ).As("s");
c.InnerJoin(c).On(c.CustomerID == o.CustomerID);

CustomersCollection coll = new CustomersCollection();
coll.Load(c);

The resulting SQL generated by our SqlClientProvider is as follows.

SELECT c.[CompanyName],c.[Country],s.[Freight] 
FROM
(
    SELECT o.[CustomerID],AVG(o.[Freight]) AS 'Freight' 
    FROM [Northwind].[dbo].[Orders] o
    GROUP BY o.[CustomerID]
) AS s
INNER JOIN [Northwind].[dbo].[Customers] c
ON c.[CustomerID] = s.[CustomerID]

The resulting rows look like this:

CompanyName                              Country         Freight
---------------------------------------- --------------- -------
Alfreds Futterkiste                      Germany         37.5966
Ana Trujillo Emparedados y helados       Mexico          24.355
Antonio Moreno Taquería                  Mexico          38.36
Around the Horn                          UK              36.3038
Berglunds snabbköp                       Sweden          86.64
Blauer See Delikatessen                  Germany         24.0371
Blondesddsl père et fils                 France          56.6963
Bólido Comidas preparadas                Spain           63.7233
Bon app'                                 France          79.8747
Bottom-Dollar Markets                    Canada          56.7107

EntitySpaces SubQuery in the Where Clause

Here we have returned a list of countries where customers live where there is no supplier located in that country. Here we pass a subquery to the NotIn() operator.

SuppliersQuery supp = new SuppliersQuery("supp");
supp.es.Distinct = true;
supp.Select(supp.Country);

CustomersQuery cust = new CustomersQuery("cust");
cust.es.Distinct = true;
cust.Select(cust.Country);
cust.Where(cust.Country.NotIn(supp));

CustomersCollection coll = new CustomersCollection();
coll.Load(cust);

The resulting SQL generated by our SqlClientProvider is as follows:

SELECT DISTINCT cust.[Country] 
FROM [Northwind].[dbo].[Customers] cust
WHERE cust.[Country] NOT IN
(
    SELECT DISTINCT supp.[Country] 
    FROM [Northwind].[dbo].[Suppliers] supp
)

The resulting rows look like this:

Country
---------------
Argentina
Austria
Belgium
Ireland
Mexico
Poland
Portugal
Switzerland
Venezuela

Although not shown here it is also possible to use a subquery in the Join statement. Of course, subqueries can be nested in various ways too. We hope this gives you a glimpse of what is coming in ES2008. We are making great progress. The beauty of course is this will work on all of the databases we support.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Thursday, February 07, 2008 10:31:21 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, January 19, 2008
kick it on DotNetKicks.com

This is only a preview of some of the big things planned for ES2008, this is not the roadmap. There are many items such as esDataSource improvements and various fixes that will be covered in the roadmap which will be published soon. ES2008 is going to roll out a little differently than have our past releases. Rather than rolling out releases at a rapid rate we are going to have two main releases for ES2008. This will result in greater productivity for the EntitySpaces team, and greater functionality for our customers, as the act of cutting a release itself burns a lot of cycles. We have dates in mind for these releases and they will published in the official roadmap. We have created a special place in our forums to talk about this preview and our upcoming roadmap when released, that is the place to make your wishes and concerns known. Let's take a very high level look at some of these key features.

New Code Generation Model

The EntitySpaces team has decided a new code generation model is needed for several reasons. One of the main reasons we have chosen a new model is to make it easier for customers to extend EntitySpaces. However, this new model will also make development much easier for the EntitySpaces team as well. The new EntitySpaces code generator will operate as an ASP.NET website hosted on your local machine or on a server within in your organization. However, even though we have chosen this approach we are not precluded from running these same templates under the CodeDOM model in the future as CodeSmith templates can use code behind pages. Here are some of the advantages of going to a pure ASP.NET website based code generation model.

  • No need to write our own code generator as ASP.NET itself can execute the templates naturally.
  • Developers are already familiar with this model.
  • Full Intellisense including Intellisense for our new esMetadataEngine.
  • Easy debugging, just step right into your templates while in Visual Studio (including Express versions).
  • Custom Objects can be formed that are different than what the database schema describes (true mapping).
  • Better template recording and playback capabilities.

Take a look at this high level diagram

image

We have received some very good input on our forums that had an impact on the feature set for ES2008, specifically, the concept of a template stack. The EntitySpaces Core templates will be required and generate the main classes. The EntitySpaces Optional templates are just that, optional, and will generate things such as our WCF proxy classes. The Custom User templates are templates written by our customers. These templates can be created, shared, even sold by 3rd party developers. We hope to have a place where customers can publish their templates, and our code generator will be able to display those for you and you can then optionally pull them down for inclusion into your template stack. The concept behind the template stack is that customers can both extend EntitySpaces with new functionality, and replace standard functionality that we provide in the optional templates, by swapping our templates out and theirs in. The idea is that users can really begin to customize EntitySpaces without the fear of losing edits to templates. These templates are written as .ASCX controls with code behind pages, and therefore, support for CodeSmith is one of our goals as well. Our templates will be written in C# as they are now, however EntitySpaces will continue to generate both C# and VB.NET architectures as always.

Our new esMetadataEngine will be different from the MyMeta engine in MyGeneration. It will not support JScript or VBScript and therefore will have no need for COM Interop, nor the need to be registered in the registry. In addition to reading the metadata from your database schema, our new esMetadataEngine will be able to serve up the metadata for custom designed objects, or mapped objects created by the customer that represent objects not specifically described in the database. Also, the esMetadataEngine will not be "hard-bound" to any 3rd party ADO.NET providers eliminating upgrade issues when vendors publish new providers. Of course, the esMetadataEngine will be based on the Factory pattern, and allow 3rd parties to add support to EntitySpaces for databases not supported by the EntitySpaces team.

Most likely the data behind our new ASP.NET code generation model will be saved in an SQL CE ".sdf" database. This will include things such as configuration data, connection strings, and template stack information.

EntitySpaces Class Streamlining

The generated EntitySpaces classes are going to be streamlined. A lot of the functionality that can be pushed down in the EntitySpaces "Core" will be, while many other things like the ".str" methods, and so on, are going to be made optional. Also, you will be able to have null constructors in your Custom classes. Basically, you will be able to generate bare bones EntitySpaces classes, and then, enhance them as you see fit using our new customizable template stack approach. Remember, 3rd parties can publish their templates for inclusion into your stack. There could be a few minor breaking changes as a result of this streamlining but we hope to keep them to a minimum, as we think we have one of the best APIs in the business.

DynamicQuery API Enhancements

We will be adding some powerful enhancements to further expand the power of the EntitySpaces DynamicQuery API.

We will be adding the ability to perform SubSelects at various places within the DynamicQuery API. A SubSelect will merely be another DynamicQuery inserted somewhere in the syntax. This is not unlike how our joins are performed. Let's take a look at a sample SubSelect statement.

ProductsQuery avg = new ProductsQuery("a");
avg.Select(avg.UnitPrice.Avg());

ProductsCollection p = new ProductsCollection("p");
p.Query.Select(p.Query.ProductName);

p.Query.Where(p.Query.UnitPrice > avg);  // <= SubSelect
p.Query.Load();

This will generate the following SQL:

SELECT p.ProductName
FROM Products p
WHERE p.UnitPrice>(SELECT AVG(a.UnitPrice) From Products a)

We will also be adding native language casting operations. There are many times when you need to coerce a data type from one type to another in SQL syntax, and currently, there is no way to express this in EntitySpaces. Below is an example of how this will work.

EmployeesCollection coll = new EmployeesCollection();
coll.Query.Select
(
    (coll.Query.LastName + " was hired on " +
        (string)coll.Query.HireDate).As("VirtualColumn")
);
coll.Query.Load();

In the sample above the (string) cast will result in the appropriate SQL being generated for the type of the database being accessed, for SQL this would be either the CAST or CONVERT function for instance to convert the SQL datetime to a varchar for concatenation.

EntitySpaces DataProvider Enhancements

Do not confuse these DataProviders with esMetadataEngine providers. EntitySpaces DataProviders are the providers used by EntitySpaces during runtime to access a database, not the providers used during code generation. These are the enhancements planned for ES2008.

  • IBM DB2 Express support.
  • VistaDB 3.3x support with VistaDB Stored Procedure Generation.
  • SQL CE Desktop Support.
  • 3rd Party Support will be enabled.

Summary

We know this is a lot to tackle for ES2008 and that is why we have chosen to roll this out in two releases rather than a bunch of smaller ones. We will be doing a lot of blogging on this, dive much further into various pieces, and hopefully elicit some feedback from our customer base. Also, we will publish a detailed roadmap for ES2008 in a few weeks.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Saturday, January 19, 2008 6:45:09 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Wednesday, September 19, 2007

I just had to make another post, this is so much fun. Writing queries in our enhanced dynamic query language is totally awesome, and so powerful. I'm writing some unit tests to go into our massive NUnit test suite and just had to post these ...

public void JoinWithArithmeticExpressionOrderByCalulatedColumn()
{
    // Notice I create a calulated columns based on the TotalSales, then Order by it descending
    CustomerQuery cust = new CustomerQuery("c");
    OrderQuery order = new OrderQuery("o");
    OrderItemQuery item = new OrderItemQuery("oi");

    cust.Select(cust.CustomerName, (item.Quantity * item.UnitPrice).Sum().As("TotalSales"));
    cust.InnerJoin(order).On(order.CustID == cust.CustomerID);
    cust.InnerJoin(item).On(item.OrderID == order.OrderID);
    cust.GroupBy(cust.CustomerName);
    cust.OrderBy("TotalSales", esOrderByDirection.Descending);

    CustomerCollection coll = new CustomerCollection();
    coll.Load(cust);
}

The SQL produced:

SELECT c.[CustomerName],SUM(oi.[Quantity]) AS 'TotalSales'
FROM [ForeignKeyTest].[dbo].[Customer] c
JOIN [ForeignKeyTest].[dbo].[Order] o ON (o.[CustID] = c.[CustomerID])
JOIN [ForeignKeyTest].[dbo].[OrderItem] oi ON (oi.[OrderID] = o.[OrderID])
GROUP BY c.[CustomerName]
ORDER BY TotalSales DESC

The result set is CustomerName / TotalSales sorted in decending order by TotalSales ...

Another query I wrote merely concatenated the Employee FirstName and LastName columns, and upper cased them.

public void ArithmeticConcatenationNoJoinWithSubOperator()
{
    EmployeeCollection coll = new EmployeeCollection();
    EmployeeQuery q = coll.Query;

    q.Select( (q.LastName + "," + q.FirstName).ToUpper().As("FullName") );
    q.OrderBy(q.LastName.Ascending);

    coll.Query.Load();
}

I've seen many of our competitors query languages, I think by far EntitySpaces has the cleanest, most straight-forward syntax, by light years in most cases. We've got some really cool stuff coming, hang on ...

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net


kick it on DotNetKicks.com
posted on Wednesday, September 19, 2007 7:47:35 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Tuesday, September 18, 2007

The EntitySpaces Dynamic Query API will soon be sporting Join’s and Arithmetic Expressions. The syntax is so elegant even LINQ enthusiasts will take pause. Let’s take a look at how you would do a join using the enhanced EntitySpaces DynamicQuery. Note that we are using all of your existing objects to build the query.

Performing Joins …

CustomersQuery cust = new CustomersQuery ("c");
OrdersQuery orders = new OrdersQuery ("o");
OrderDetailsQuery details = new OrderDetailsQuery ("d");

cust.Select(cust.ContactName, details.Quantity.Sum().As("TotalQuantity"));
cust.InnerJoin(orders).On(cust.CustomerID == orders.CustomerID);
cust.InnerJoin(details).On(orders.OrderID == details.OrderID);
cust.Where(cust.ContactName.Like("%Mike%"));
cust.GroupBy(cust.ContactName);

CustomersCollection coll = new CustomersCollection ();
coll.Load(cust);    // Load it …

Now that is a pretty sweet syntax …

Of course, RightJoin, LeftJoin, and FullJoin are also supported. The nice thing about this approach is that you are spoonfed the syntax via intellisense, no need to stop and create a view (although you can if you want to and generate your business entities off of the view). The "o", "c" and "c" shown above are merely the aliases used when building the SQL.

Arithmetic Expressions

You can now use arithmetic expressions in your query's. Notice how you can use the natural language syntax with * / + - and %. Take a look at this sample …

CustomersQuery cust = new CustomersQuery ("c");
OrdersQuery orders = new OrdersQuery ("o");
OrderDetailsQuery details = new OrderDetailsQuery ("d");

cust.Select(cust.ContactName, (details.Quantity * details.Price).Sum().As("TotalPrice"));
cust.InnerJoin(orders).On(cust.CustomerID == orders.CustomerID);
cust.InnerJoin(details).On(orders.OrderID == details.OrderID);
cust.Where(cust.ContactName.Like("%Mike%"));

CustomersCollection coll = new CustomersCollection ();
coll.Load(cust);    // Load it …

How Does this Effect Binding?

Your EntitySpaces collections will now provide a new method named LowLevelBind(). Normally, you bind directly to the properties in your EntitySpaces entities. However, when joins are in play you are bringing back columns that aren’t in your entities. Thus, the LowLevelBind will bind directly to the underlying DataTable. The are other ways of course using EntitySpaces but we wont cover those in this post.

grid.DataSource = coll.LowLevelBind();

Can I still Save an Entity that was Built off a Join?

The answer is "yes". Of course, it will only save to the main table, in the above case the Customer table.
We already have this implemented and are hoping to have a beta out with joins and arithmetic expressions around October 1st, 2007.

These new features will be available for all of the many databases supported by EntitySpaces.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Tuesday, September 18, 2007 11:22:28 AM (Eastern Standard Time, UTC-05:00)  #    Comments [2]