Sunday, April 06, 2008

We are cranking very hard on EntitySpaces 2008. However, we are doing many things in parallel. We thought we would take this time to relay some of work going on here at EntitySpaces behind the scenes and to relay some long term strategy. None of these side tasks are drawing tremendous energy away from our main focus, which is, EntitySpaces 2008.

 

Side Tasks

 

Silverlight

 

We are working with a Silverlight expert to create a sample that demonstrates running EntitySpaces under Silverlight. These are the scenarios we are investigating:

 

1) Hosting the EntitySpaces assemblies under Silverlight in the browser.

2) Hosting our lightweight proxies under Silverlight in the browser.

 

This research is just getting underway and will let you know more soon. The idea is to make it so that you can write Silverlight pages using EntitySpaces. We know in some form this will be possible.

 

Site Redesign

 

EntitySpaces is undergoing a site redesign and logo change. Our goal is to make the changeover simultaneously with the release of ES2008.

 

LINQ to SQL

 

There is some investigation underway that might allow our Microsoft SQL users to check a checkbox during the code generation process that would allow them to use native LINQ to SQL calls to populate EntitySpaces. This is very much at the beginning of the R&D process. However, we are not creating our own LINQ provider. If we can offer you LINQ through the existing providers then we will do so. We are very committed to our DynamicQuery API and will continue to expand it in big ways. In no way will LINQ replace our DynamicQuery API.

 

The .NET Micro Framework

 

We will investigate this at some point after ES2008 is shipped. Whether or not it makes sense for us to support the .NET Micro Framework we are unsure of at this time. We are committed to ensuring that EntitySpaces remains tiny and continues to run under all possible .NET environments. Our Mono support and Compact Framework support will always be very important to us.

 

Long Term

 

After we ship EntitySpaces 2008 we will begin to solidify the design goals of our next release. The ES2008 release essentially decouples us from any particular code generator. We now use our own metadata engine and essentially only use code generators to gather the user input and execute our templates. Our templates are really just normal ASP.NET pages with <% %> tags and literal content and this is inline with our long term goals.

 

Visual Studio Shell

 

We have done some investigation into the Visual Studio Shell (both integrated and isolated) and we think this could be the platform we choose to go with long term. This would mean that we would no longer use code generators and instead would do the code generation ourselves. Since the Visual Studio Shell supports isolated mode this has the added advantage of still supporting the smaller shops that cannot afford Visual Studio (integrated runs inside of Visual Studio itself).

 

The Modeler

 

EntitySpaces will support custom domain model building. We currently generate the hierarchical object model from the foreign keys in the database. In the future, and in conjunction with the VS Shell application mentioned above, you will be able to design your own object model that is not tied to the physical database schema. However, we will not use XML or other such devices at runtime, we will simply generate the code using your virtual domain model. We will still support our current approach which is solely based on the database schema also.

 

Template Engine

 

Imagine a template engine that is based on snippets. Currently we have Master templates which execute sub-templates where a sub-template might be and entity class, a collection class, or query class. Our new template engine will be based on snippets. A sub-template itself would merely be a collection of snippets where each little "set" of functionality is a snippet. Writing a snippet would be very simple and within the grasp of all developers.


A snippet could be a property creation snippet, an INotifyChanged snippet, and so on. This would allow users to swap in their own snippets as well as to share them. Our standard templates would be based on many individual snippets. To customize or extend EntitySpaces would no longer require hand changing templates, simply restack and or replace the snippets through a UI not hand editing.

Our shell based application would have its own underlying database which would store templates and other settings. You would be working with templates graphically, where each snippet is a different colored block. You could then right mouse on a snippet and choose remove it and drag and drop other snippets from the available snippet library onto a template to further customize it. Users will be able to post snippets to an online webservice hosted by EntitySpaces that our shell app will make available to all EntitySpaces users. At some point, after ES008 ships, we will post some images of our new approach.

We feel this is going to revolutionize the way people view code generation as we will open this up to the masses, not to just code generation experts. The Visual Studio Shell combined with our new Modeler will take our already stellar architecture to new levels.

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 06, 2008 11:24:03 AM (Eastern Standard Time, UTC-05:00)  #   
 Monday, March 31, 2008

The first EntitySpaces 2008 Beta is available on our download page. If you have the Alpha installed you should uninstall it before installing the Beta. There is no need to uninstall EntitySpaces 2007, you can run ES2007 and ES2008 side by side.

Limitations

Only our Microsoft SQL provider is supplied with this Beta and there is no Compact Framework support yet. Finally, only the C# templates are included. MyGeneration and CodeSmith are supported however in this single install.

New Features

The EntitySpaces 2008 Beta includes sub queries and casting.

Changes for our MyGeneration Users

The EntitySpaces templates for MyGeneration now use there own user meta data. You will find a new template in the root of the EntitySpaces 2008 namespace in MyGeneration called UserData. The first time you run it the template will convert your old user meta data (if any) to our new format and file name (esUserData.xml). Also, you will need to re-setup any custom settings you have made in the Settings template (replaces esPluginSettings) located in the root also.

Also, a gentle reminder that we cannot spend our time writing complex queries for our users. Look at our samples on our blog linked under "New Features" above.

Summary

We are now going to start converting our other providers (including our Compact Framework providers) very rapidly. It could be that we decide to release a beta before the schedule April 27th Beta as listed on our roadmap. So if you aren't using SQL Server there might be a chance to get started before April 27th.

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, March 31, 2008 2:50:18 AM (Eastern Standard Time, UTC-05:00)  #   
 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)  #   
 Saturday, March 15, 2008

The EntitySpaces 2008 Roadmap is pretty aggressive and adds a lot of new functionality to the EntitySpaces Architecture. The EntitySpaces 2008 Alpha is already available. The remaining target dates are as follows:

March 30th - 1st Beta

April 27th   - 2nd Beta

May 11th    - Official Release

The March 30th Beta will have both CodeSmith and MyGeneration support, and will contain the C# templates, but we are unsure if the VB.NET templates will be in the March 30th release. It could be that we sneak an extra beta out if the VB.NET templates don't make the March 30th beta.


The Roadmap

With CodeSmith Support, SubQueries, and Casting (see below) already pretty much completed, we are working on the final major portion of the EntitySpaces 2008 release. That is some class reorganization. The big change as far as class layout for ES2008 is that we intend to make the Custom classes no longer be partial classes. This means that your Custom classes and Generated class could then be housed in different assemblies. We have theorized how this is going to work and the coding is underway, hopefully, we will not hit a snag as this has been asked for quite often. However, there is an impact. For the first time since EntitySpaces shipped, we are going to require a change to your Custom Classes. This will be easy to do however and may not require any hand coding. All of the classes in the Generated layer will now be abstract. For those who have been using EntitySpaces without generating the Custom classes, this will no longer be an option, you will need to generate them. We think the over all added flexibility more than justifies this change.

Okay, now on to the list ...

These are listed in no particular order

The next provider that EntitySpaces will add to its list of supported databases will be the IBM DB2 Express database. Date of inclusion, however, has not been determined.

But I don't see my issue here?

Our goal is to complete all of the above by the target dates, and we are making good progress. However, the schedule is aggressive. If there is something we have missed, please post a note in our EntitySpaces 2008 forums section with ES2008 Wish - { your title }

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 15, 2008 12:40:02 PM (Eastern Standard Time, UTC-05:00)  #   
 Sunday, March 09, 2008

EntitySpaces 2008
Persistence Layer and Business Objects for Microsoft .NET
 

kick it on DotNetKicks.com

imageWe are very excited to offer this Alpha release for those who want to get a head start with EntitySpaces 2008 (ES2008). This Alpha release supports only C# class generation from within CodeSmith, and only supports Microsoft SqlServer. A subsequent beta release will support CodeSmith, MyGeneration, C#/VB.NET classes, and all of our providers. The Alpha release comes with both .NET 2.0 and .NET 3.5 runtimes. The Alpha comes with the new, very powerful, SubQuery Enhancements to our DynamicQuery API. Please be sure to look at the "Getting Started" document that will be on your Start Menu after installation. It contains all of the information you need to get started (and it's very easy). CodeSmith users can generate their EntitySpaces classes right from within Visual Studio. Our EntitySpaces templates work well in CodeSmith project files, as well. All of our testing was done with CodeSmith 4.1.2.

ES2008 is neutral in regards to which code generator you decide to use. ES2008 will support both CodeSmith and MyGeneration. Part of what makes this possible is that we now provide our own metadata engine. Our meta data engine is named EntitySpaces.MetadataEngine.dll, and is installed in the GAC during installation. The EntitySpaces.MetadataEngine assembly is NOT redistributable, nor can it be used to build applications. It can be used to create custom templates for EntitySpaces, but again, the EntitySpaces.MetadataEngine assembly cannot be distributed. It must be obtained from EntitySpaces, LLC. Our metadata engine uses OLEDB for accessing data. CodeSmith users can use our easy setup button on the template UI to do everything very easily. This is all covered in the Getting Started PDF.

Our Compact Framework assemblies (although not in this beta) are being renamed to "CF" instead of "Ce". For example, EntitySpaces.Core.Ce.dll is now EntitySpaces.Core.CF.dll. This makes things much more understandable, and avoids confusion with SQL Server CE.



image
For a quick tutorial, see our video demonstrating how to generate your EntitySpaces 2008 Architecture HERE (13 meg)



THE ENTITYSPACES 2008 ASSEMBLIES

EntitySpaces.Core.dll Contains the esEntity/esEntityCollection classes
EntitySpaces.Interfaces.dll Providers link to this assembly
EntitySpaces.Loader.dll Loader, uses reflection
EntitySpaces.LoaderMT.dll Loader, medium trust support (no reflection)
EntitySpaces.MSAccessProvider.dll Provider - Microsoft Access
EntitySpaces.MySqlClientProvider.dll Provider – MySQL
EntitySpaces.OracleClientProvider.dll Provider – Oracle
EntitySpaces.SqlClientProvider.dll Provider - Microsoft SQL Server
EntitySpaces.SqlCeClientProvider.dll Provider - Microsoft SQL CE desktop provider
EntitySpaces.VistaDBProvider.dll Provider - VistaDB
EntitySpaces.NpgsqlProvider.dll Provider - PostgreSQL
EntitySpaces.Web.Design.dll esDataSource (design time support for ASP.NET)
EntitySpaces.Web.dll esDataSource (design time support for ASP.NET)
   
Compact Framework Assemblies  
EntitySpaces.Core.CF.dll Contains the esEntity/esEntityCollection classes
EntitySpaces.Interfaces.CF.dll Providers link to this assembly
EntitySpaces.Loader.CF.dll Loader, uses reflection
EntitySpaces.LoaderMT.CF.dll Loader, medium trust support (no reflection)
EntitySpaces.SqlCeClientProvider.CF.dll Provider - Microsoft SQL CE
EntitySpaces.VistaDBProvider.CF.dll Provider - VistaDB CE

 
In the list above, we have not listed any of the new providers we plan on adding. Only the Microsoft SQL Server provider is included in this Alpha, and none of the Compact Framework assemblies are included. EntitySpaces 2008 can be installed side-by-side with EntitySpaces 2007. DO NOT install EntitySpaces 2008 over the top of your EntitySpaces 2007 installation. The folder structure for ES2008 is significantly different than the ES2007 layout.

Download the EntitySpaces 2008 Alpha Now, No Registration Necessary ==> DOWNLOAD 

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 09, 2008 7:57:57 PM (Eastern Standard Time, UTC-05:00)  #   
 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)  #   
 Thursday, February 28, 2008
We are calling this an Alpha however EntitySpaces is well tested. The alpha will have passed all of our unit tests so it will be very stable. The only reason we are not calling it a Beta is that initially we are only supplying the C# templates, our VB.NET templates will follow in the subsequent Beta. You will not have to register on our site to download the Alpha (same goes for our trial versions).

If you are a CodeSmith fan consider taking a look at EntitySpaces, here are some of the features:

  • Mono Support
  • Medium Trust Support
  • Compact Framework Support
  • Hierarchical Data Models
  • Powerful Dynamic Query API
  • Data Provider Independence
  • Binary and XML Serialization
  • Two Different Transaction Models
  • Saving via Stored Procedures or Dynamic SQL
  • Design Time Data Binding
  • Generated from your Database Schema
  • LINQ Support for Collections 
  • Regenerate Without Losing Custom Business Logic
  • Admin Grid Template Suite for ASP.NET
  • Admin Grid Template Suite for DotNetNuke
  • Source Code Available

Providers Available:

  • Microsoft SQL Server / SQL CE
  • Microsoft Access
  • Oracle
  • MySQL
  • VistaDB 
  • PostgreSQL  
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 28, 2008 9:33:52 AM (Eastern Standard Time, UTC-05:00)  #   
 Tuesday, February 26, 2008

VistaDB 3.3 Express Edition

VistaDB has decided to release a free Express version. Here is an excerpt from their Blog post:

What is it?

VistaDB Express is a free edition of VistaDB for non commercial use.  This includes hobbyists, mono developers, open source projects, personal websites, user groups, sample application, schools, and much much more.

Why an Express Edition?

We get asked quite a bit about distribution with free and open source projects (especially mono developers), we needed  a license to specifically help these developers use all the cool features of VistaDB in their community as well.

Microsoft decided a long time ago that the Express Development tool (VB Express, C# Express, C++ Express) editions are not allowed to load third party plugins.  These editions were specifically aimed at the non professional developer community.  Since they can't load the GUI plugins for Visual Studio 2005 and 2008 anyway, we decided to simplify the offering for these users.

Where do I get it?
Read the rest of the story HERE ...

posted on Tuesday, February 26, 2008 12:24:03 PM (Eastern Standard Time, UTC-05:00)  #