WAQS: Multi edmx and specifications methods

7 reasons to use WAQS

WAQS documentation

 

It is often recommended to use small edmx (one per functional module for example) instead of one huge.

Why using many edmx instead of only one?

First, even if the availability to have many schemas in the same edmx improves user experience, using small models is better for readability and understanding than a huge one.

In addition, using a huge model could be catastrophic for the first query.

This point could be reduce using EntityMappingGeneratedViews which allow to pre-generate information that Entity Framework would have to calculate at runtime otherwise.

Note that WAQS generates them.

Another point that encourages you to use many edmx is the fact that it’s easier to query the whole entities instead of querying one part of them. But, if you are building some products for example it’s probably useless to get all information about associated suppliers. We can imagine that Id, CompanyName, ContactName and Phone are enough.

So we may use two edmx with two different Supplier entity types: one complete for a supplier module and one light for the Product module.

So, in this case we use two different Supplier type.

Now the key point is the fact that, sometimes, you want to share specifications between both Supplier entities.

How to share specifications between different edmx entities?

We need a common type between the two Supplier entities.

So the idea to achieve it is to use an interface. We decorate this interfacet with an attribute of type IEntityAttribute that indicates to WAQS that it has to replace it by the only one entity in the model that implements this interface:

[IEntity] 
public
 interface ISupplier
{
    int Id { get; }
    string CompanyName { get; }
    string ContactName { get; }

    string Phone { get; }
}


Then we extend Supplier classes using partial in order to let them implenting ISupplier.



Now we can define specifications on it. For example:



public static string GetSupplierName(this ISupplier supplier)
{
    return string.Concat(supplier.CompanyName, " - ", supplier.ContactName);
} 










 



How to use this with navigation properties?



If you want to use interfaces instead of entities we also have to use interfaces for navigation properties.



Interfaces navigation properties must have the same name than model ones and must be implemented explicitly.



Ex:


[IEntity]
public interface IProduct
{
   IEnumerable<IOrderDetail> OrderDetails {get; }
}

[IEntity]
public interface IOrderDetail
{
   double UnitPrice {get;set; }
   short Quantity {get;set; }
   IProduct Product {get; }
}

partial class Product : IProduct

   IEnumerable<IOrderDetail> IProduct.OrderDetails 
   { 
       get { return OrderDetails; } 
   }
}

partial class OrderDetail : IOrderDetail
{
   IProduct IOrderDetail.Product
   {
       get { return Product; } 
   }
}

Then you can use it in specifications methods:



public static int GetNumberSold(this IProduct product)
{
    return product.OrderDetails.Sum(p => p.Quantity);
}

public static Error ValidateOrderDetailProductUnitPriceEqualsProductUnitPrice(this OrderDetail od)
{
    if (od.Product.UnitPrice != od.UnitPrice)
        return new Error { Criticity = Criticity.Warning, Message = "Order detail unit price should be the same the product one" };
    return null;
}


Then, in order to use the specifications in many projects, you just have to add the specifications folder path in waqs configuration file:



<Specifications>
  <Specification SlnFilePath="SlnPath" CsprojPath="Project1Path" FolderPath="Folder1Path" />
  <Specification SlnFilePath="SlnPath" CsprojPath="Project2Path" FolderPath="Folder2Path" />
</Specifications>


 



Note that if you want to use the same DB in many edmx, you have to use an unique edmx name and an unique Entity Container Name.

This entry was posted in 16868. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>