-
Notifications
You must be signed in to change notification settings - Fork 4
Step by step instructions for using M2M with OpenRIAServices
The instructions below assume that you'll be using Entity Framework code first and DbContext. If you're using an alternative DAL, you can still use M2M4Ria but the steps marked with (*) will be slightly different.
- Add the OpenRIAservices.M2M Nuget package to your RIA Service server project. This will also add the packages OpenRIAServices.M2M.LinkTable, EntityFramework, OpenRiaServices.FluentMetadata, and OpenRiaServices.T4, to your project. This package will add extensions to the FluentMetadata package that enables you to specify what your M2M associations are. Furthermore, the package will add an entity generator that integrates with RIA Services code generation framework.
- optional: If your data model is defined in a different project, add the Nuget package OpenRIAServices.M2M.LinkTable to that project as well. You'll need the generic LinkTable class provided by this package in your data model (I'll come to that later).
- Add the OpenRIAServices.M2M.Silverlight Nuget package to your Silverlight project. This package adds the Silverlight M2M view on link table entities to your Silverlight project.
- Define a LinkTable entity type that connects both entity types of an M2M association. E.g., given two entity types Product and Order, you can define a link table entity as follows:
public class ProductOrder : LinkTable<Product, Order> {}
- Define "link table views" for your M2M associations for both entity types involved in an M2M Association. E.g., for Product and Order this will be:
using OpenRiaServices.M2M;
public partial class Product
{
public ICollection<ProductOrder> Product_ProductOrderSet
{
get
{
return OrderSet.ProjectObject1(this, x => x.Order_ProductOrderSet);
}
}
}
public partial class Order
{
public ICollection<ProductOrder> Order_ProductOrderSet
{
get
{
return ProductSet.ProjectObject2(this, x => x.Product_ProductOrderSet);
}
}
}
ProjectObject1 and ProjectObject2 are extension methods that project an entity type to the corresponding property of a link table entity.
- (*) Instruct entity framework to ignore these link table views from your entity model, such that the link table entities will not be populated to your data store. E.g., by adding .Ignore expressions as in the example below:
public class MyEFContext : DbContext
{
public DbSet<Product> ProductSet { get; set; }
public DbSet<Order> OrderSet { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Product>().HasMany(x => x.OrderSet).WithMany(x => x.ProductSet);
modelBuilder.Entity<Product>().Ignore(x => x.Product_ProductOrderSet);
modelBuilder.Entity<Order>().Ignore(x => x.Order_ProductOrderSet);
}
}
- Configure your domain service to use the Fluent metadata API.
[EnableClientAccess](EnableClientAccess)
[FluentMetadata(typeof(MetadataConfiguration))](FluentMetadata(typeof(MetadataConfiguration)))
public class MyDomainService : DbDomainService<MyEFContext>
{
}
- Define a fluent metadata configuration class. E.g.,
public class MetadataConfiguration : IFluentMetadataConfiguration
{
public void OnTypeCreation(MetadataContainer metadataContainer)
{
}
}
- In the OnTypeCreation method, specify your M2M association using the fluent API, e.g.,
metadataContainer.Entity<Product>()
.Projection(x => x.OrderSet)
.M2M(x => x.Product_ProductOrderSet, x => x.Order_ProductOrderSet, x => x.ProductSet);
This expression specifies that the property Product_ProductOrderSet is the link table view for the property OrderSet in Product, and that Order_ProductOrderSet is the corresponding link table for property ProductSet in Order. With this information in place, the M2M entity generator is able to extend the generated entities in your Silverlight client with link table collections and with M2M views for them (i.e., the entity Product will have an M2M property OrderSet and Order will have an M2M property ProductSet).
- (*) Extend the domain service with Insert and Delete operations for your link table entities. Since link table entities are transmitted between your Silverlight client and domain service, the latter must have Insert and Delete operations defined for them. Link table entities are read-only because they consist only of a composite key (which will not change once created). For this reason, there is no Update method needed in your domain service. Moreover, since link table entities are always queried via their associated entities, there is no Query method needed for them. However, you are free to define one when needed.
using OpenRiaServices.M2M.DbContext;
public void InsertProductOrder(ProductOrder ProductOrder)
{
var Product = ProductOrder.FetchObject1(ChangeSet, DbContext);
var Order = ProductOrder.FetchObject2(ChangeSet, DbContext);
Product.OrderSet.Add(Order);
DbContext.ChangeTracker.DetectChanges();
}
public void DeleteProductOrder(ProductOrder ProductOrder)
{
var Product = ProductOrder.FetchObject1(ChangeSet, DbContext);
var Order = ProductOrder.FetchObject2(ChangeSet, DbContext);
DbContext.LoadM2M<Product, Order, ProductOrder>(Product, Order);
Product.OrderSet.Remove(Order);
DbContext.ChangeTracker.DetectChanges();
}
FetchObject1, FetchObject2, and LoadM2M are extension methods specific for DbContext that simplify the implementation of the Insert and Delete methods.
- (*) Make sure you include the M2M associations in the query results of your entities. E.g., add "Include" expressions to your queries, like so:
public IQueryable<Order> GetOrderSet()
{
return DbContext.OrderSet.Include(x => x.ProductSet);
}