21 people following this project (follow)

Project Description
M2M4RIA is a mechanism which adds support for many-2-many (M2M) relations to WCF RIA services. It requires Entity Framework 4.0 and RIA services 1.0.

Latest Version
Help Needed
  • I'm looking for people who want to help in improving m2m4ria on the following aspects:
    • I want to improve/simplify the process of integrating m2m4ria in your projects by using T4 Scaffolding and NuGet. This could replace several manual steps by automated ones.
    • I want to add support for code-first Entity Framework models to m2m4ria. Given the recent developments of code-first, this would be a great addition to m2m4ria.
Please, let me know if your are interested.

M2M Relations
M2M relations are (usually) defined in terms of three data base tables, E.g.:


ProductOrderWithLinkTable.png
Figure 1: Many-2-many with explicit join tables

Entity Framework is able to "hide" the join table (i.e., the table connected to Product and Order). This gives the ability to directly access an Order's collection of products. Underneath, entity framework also uses the join table. Entity framework only hides a join table if the table exactly has two columns: one of type A and one of type B. If more columns are present, the join table becomes visible in the entity model.

M2M and RIA
Unfortunately, RIA services doesn't support M2M relations with hidden join tables. If EF hides the join table, then RIA will not expose the M2M relation in the domain service. A common way to let RIA expose the M2M relation is by having the join table visible in the entity model, by introducing an additional column in the join table. The drawback of this approach is that one has to deal with these join table objects whenever accessing the M2M relation. So, instead of writing A.BSet.Add(new B()); one has to write something like: A.ABSet.add(new AB{B = new B()}); Querying and deleting also is a little more cumbersome. Another disadvantage is that, in order to enable M2M in RIA, the database needs to be modified, as well as the entity model. So, even when working directly on the entity model, one also has to deal with join table objects.


Supporting M2M in RIA
ProductOrderAsM2M.png
Figure 2: Many-2-many without explicit join tables
The M2M4Ria project aims at providing an implementation of M2M in RIA that does not require join tables in the entity model or in RIA. It provides full CRUD operations on M2M relations. The idea is to let RIA operate on our own provided join types, rather than on join types generated by EF. These join tables only serve communication between client and server, such that M2M relations can be sent and received to a remote client. At the client side a "view" on the M2M relations shows only B's to A, and A's to B (see picture below). You therefore no longer need join table objects to access M2M relations. Your entity model doesn't need any change for this.

m2m4riaoverview.png
Figure 3: M2M Views
Installation

The distribution consists of three directories contains a couple of Visual Studio 2010 projects:
  • M2M4Ria. This directory contains the implementation of the m2m support for RIA. The directory consists of three sub directories (Client, Server, and Shared), each holding one or more T4 template files. How to use them is described below.
    • Server/M2M4RiaEntities.ttinclude is a T4 template that generates join types and extends EF types with join type collections.
    • Server/M2m4RiaLinqToEntitiesDomainService.ttinclude:T4 script that generates domain service operations for these join types.
    • Client/M2M4RiaDomainContext.ttinclude is a T4 template that generates some extensions to the domain context and extends the RIA entity types with M2M collections.
    • Shared/M2M4RiaShared.include contains functionality to identify m2m relations in your entity model
  • M2M4RiaDemo. This directory holds a Silverlight 4.0 demo application that you can use for playing with m2m relations in a very basic entity model, with just a single m2m relation.
  • M2M4RiaTests. This directory holds a couple of projects that define unit tests for testing the Silverlight part of m2m4ria and the server part.

Usage

To use m2m4ria in your project you need to integrate and configure three generators: M2M4RiaEntities, M2M4RiaLinqToEntitiesDomainService, and M2M4RiaDomainContext. These generators are responsible for generating join type entities, generating CRUD operations in your domain service for them, and extending client-side entities with m2m entity collections, respectively.

All three generators require a little configuration, which is typically defined in a '.ttinclude' file and shared by the three generators. The following items need to be configured:

Item Description Example (from M2M4RiaDemo project
EdmxFilePath Defines the path to your the edmx file that contains your entity model. M2M4RiaDemo\M2M4RiaDemo.Web\Model\M2M4RiaDemoModel.edmx
EntityModelNamespace Defines the name space of your entity model M2M4RiaDemo.Web.Model
DomainServiceNamespace Defines the name space of your domain serviceM2M4RiaDemo.Web.Service
DomainServiceName Defines the name of your LinqToEntitiesDomainService domain service M2M4RiaDemoService
IsJoinTypeEntitySetAccessibleFromDomainContext*Defines whether the domain context should give direct access to the entity set of join typestrue


* This switch is to support incremental integration of m2m4ria in your projects by giving access to the entityset of join type objects via the domain context.


To add a generator and corresponding configuration to your project, create a T4 template which includes both the generator file and the configuration file.
For instance, M2M4RIADemo/M2M4RIADemo.Web contains the file 'M2M4RiaEntities.tt', which looks like:

   <#@ template language="C#" #>
   <#@ output extension=".g.cs" #>

   <#@ include file="$(ProjectDir)\..\M2MGenerator.ttinclude" #>
   <#@ include file="$(SolutionDir)\M2M4Ria\Server\M2M4RiaEntities.ttinclude" #>


The generators should be added at the following locations:

GeneratorLocationExample
M2M4RiaEntities The project that holds your edmx fileM2M4RiaDemo.Web
M2M4RiaLinqToEntitiesDomainService The project that holds your domain serviceM2M4RiaDemo.Web
M2M4RiaDomainContextThe project that holds your domain contextM2M4RiaDemo


notes
  • All generators generate code in partial classes. It is therefore required that the generators operate in the project owning the extended classes. For instance, this means that M2M4RiaEntities should do its work in the project that contains your entity model's edmx file.
  • The domain service that is initially generated by IA Services is not declared as partial. You must therefore add the 'partial' keyword to this domain service class in order to get m2m4ria to work.

Although these usage instructions might feel complicated, it is not that hard in practice. You can have a look at the M2M4RiaDemo (or browse the source code) to see how you can set up your project.



How it works
Since join tables are not present in the entity model, they are generated, as well as entity collections that return them. For example, for an M2M relation (A,B), we generate an entity AB that simulates a join table. Further, to both A and B an entity collection is added ABToASet, and ABToBSet which return a collection of join objects. These entity collections are "views" on the M2M collections of A and B, so there are no duplicated lists involved. These entity sets are only used by RIA when sending or receiving elements from an M2M relation. This is depicted in Figure 1.

Next, domain service operations are generated for the join types. Only Create and Delete operations are generated because there is no need to query join types explicitly, or to update existing ones. At the client side, entity collections are generated to the entities who are part of an M2M relation. These entity collections serve to hide the join entities. For example, for entity A, participating in the M2M relation (A,B), an entity collection "BSet" (the actual name is defined in the entity model) is generated which consists of entities of type B. This entity collection forms a view on top of the collection of join objects, hence entities are not duplicated. Since these collections are "views", adding an element b to the BSet collection of a, actually adds an element (a,b) to the collection a.ABToBSet. When this element is received by the domain service, it is decomposed into elements a and b, and b is then added to the entity collection a.BSet. EF then takes care of adding the element to the proper data base tables. Deletion of elements works similarly. The distribution consists of a set of T4 templates to generate all required code. The generator is reads your edmx file to find all M2M relations in your model.

Limitations
  1. Only single column identity keys of type int are supported. Keys of other types are not supported. Also composite keys are not supported.
  2. The join table collections are visible extensions to entity definitions. This means that, although they are intended for communication between client and server only, they are visible entity properties at both the server and the client.
  3. The generated join table collections are visible at the server and at the client.

Last edited Nov 4 2011 at 7:36 AM by MdeJ, version 18