Archive

Posts Tagged ‘DomainService’

Getting empty string default constraints to work in WCF RIA Services through a Fluent API

January 16, 2011 Leave a comment

This post is based on the excellent post by Nikhil Kothari. You should read his blog post before you continue as all I am going to introduce to how I was able to port his code to .NET 4.0 and get the Fluent API working.

First of all, let’s take a look at my file structure:

Entity Framework/RIA Services file structure

One of the issues that I have with WCF RIA Services is the whole workflow that is involved when anything changes in the data model:

  1. Exclude my partial Domain Service files.

    Fluent RIA Services - Exclude partial files

  2. Delete my Domain Service files.
  3. Open my Entity Framework (.edmx) file in the visual designer.
  4. Delete any of the model objects that have been changed. (I have found that I need to delete since Visual Studio doesn’t really serialize the changes from the database correctly.
  5. From the context menu, click on Update Model from Database…

    Fluent RIA Services - Update Model from Database

  6. Select the model objects that have changed.
  7. Build the project.
  8. Add a Domain Service.
  9. Add the partial keyword “partial” to the DomainService class.

    Fluent RIA Services - partial keyword to DomainService class

  10. Include your custom partial files in the project.

    Fluent RIA Services - Include partial files

  11. Add all of your [Include()] statements back to the .metadata file. (I have another blog post for this that get’s this to work.)
  12. Build your project.

Clearly this is a very intensively workflow and it is very easy to screw things up and your application will stop working as before. The problem I have with WCF RIA Services is that it doesn’t support or enforce default values from the database or check constraints on the client.

The use case that I am trying demonstrate is if you have a column in a table that is set as non-null but has a default value of empty string. I have a client that uses this as a standard in their database model and it becomes painful for us to get this to work. As you can see from the above workflow is that the DomainService is deleted and recreated. I have moved a lot of my custom .metadata logic to my partial file. Let’s take a look at what is required to allow empty string for a Required attribute using a slight port to Nikhil Kothari’s implementation:

public MemberValidationMetadata Required()
{
	return Required(null);
}

public MemberValidationMetadata Required(bool allowEmptyStrings)
{
	AddMetadata(new RequiredAttribute() { AllowEmptyStrings = allowEmptyStrings });
	return this;
}

This code snippet comes from the MemberValidationMetadata.cs file. It basically is an overload from the default Required() method and provides support for passing in a boolean to determine if AllowEmptyStrings is true or false.

public class rv_sbt_SiteBillTypeMetadata : MetadataClass
{
	public rv_sbt_SiteBillTypeMetadata()
	{
		this.Validation(p => p.rv_sbt_BillTypeDefinition).Required(true);
		this.Validation(p => p.rv_sbt_BillTypeDescription).Required(true);
		this.Validation(p => p.rv_sbt_BillTypeLongDescription).Required(true);
		this.Validation(p => p.rv_sbt_BillTypeName).Required(true);
		this.Validation(p => p.rv_sbt_CreatedBy).Required(true);
		this.Validation(p => p.rv_sbt_CustomerValue).Required(true);
		this.Validation(p => p.rv_sbt_ModifiedBy).Required(true);

		this.Projection(p => p.rs_sdf_SiteDocumentFormat).Include();
		this.Projection(p => p.rv_al_AccountingLink).Include();
		this.Projection(p => p.rv_obt_OrganizationBillType).Include();
		this.Projection(p => p.rv_sbtd_SiteBillTypeDetail).Include();
		this.Projection(p => p.rv_sis_SiteInstalledSubsystem).Include();
		this.Projection(p => p.rv_urbt_UserReportBillType).Include();
		this.Projection(p => p.rv_xrf_ReturnFrequency).Include();
	}
};

As you can see, I am using the overload Required method and it allows me to now support the empty string default constraint from the database. It is also possible to do this in the .metadata.cs file that is created when you create a new DomainService but I find that I prefer the Fluent API. The cool thing about this approach is that you can have both the Fluent API as well as what you get from the DomainService .metadata.cs file. The datamodel is rather large and I only add the table objects to the partial file (.metadata.partial.cs) and comment out the same definition in the .metadata.cs file shown below:

Fluent RIA Services - Comment out existing definition

Data access is still a very painful workflow for Silverlight development. I try to use metadata from a database as much as possible and this really is a good candidate for doing some code generation with T4. I do wish that we had the capability to have check contraints executed on the client without needing to write custom code but so far this doesn’t seem to work very well. I would also like to see a better alternative to forcing us to use the designer for the Entity Framework model as the only way to update and modify your model.

Perhaps an ability to code closer to what WebMatrix with Razor. That would be an awesome combination for us Silverlight developers.

Once again, thanks for reading….

Visual Studio Add-in para el Domain Service [Include()] attributo

November 10, 2010 Leave a comment

A veces uno no tiene el lujo a desarrollar applicaciones desde el modelo de objectos. Eso significa que es necessario a obtener el modelo desde la base de data. Gracias a Microsoft, tenemos el Entity Framework o Linq2Sql para ayudarnos. Ya que estamos creando una applicacion de Silverlight, todavia no hemos terminado. Tenemos que usar WCF RIA Services para el transporte de nuestros cambios en la applicacion.
Tengo un problema como WCF RIA Services no esfuerza a mantener el modelo. Lo que pasa es cualquier momento que la base de data cambia, tengo que modificar varios archivos:

  1. Actualizar el Entity Framework (. edmx) o Linq2Sql (. dbml) con el esquema datebase cambios.
  2. Borrar el DomainService que has creado, incluyendo el “Service” archivo y el “.metadata” archivo.
  3. Genere el proyecto Web que aloja el modelo.
  4. Añadir un nuevo DomainService.
  5. Agregue todos los [Include()] atributos en el “.metadata” archivo.

Ahora estas es una experiencia muy dolorosa y cada vez que puede automatizar este lo voy a hacer. Esto nos lleva al asunto de este puesto, que es una manera de automatizar por lo menos la adición del [Include()] atributo en el archivo de “.metadata”. Mi solución esta basada aquí. Hice unos modificaciones para que podemos usarlo con proyectos que tienen carpetas y para que funciona en Visual Studio 2010 RTM.

Para crear una Add-in en Visual Studio 2010, coloca nueva solución y extensibilidad en el marco del “Otros tipos de proyectos” y luego “Visual Studio Add-in”, como se muestra a continuación:

El “template” de proyecto crea lo que se muestra a continuación con la excepción del archivo MetadataHelper.cs.

Tómese su tiempo para revisar lo que contiene el Connect.cs archivo y ya que hay lógica personalizada para conseguir el MetadataHelper.cs archivo.

Básicamente, el objetivo de este complemento es para que pueda actualizar el .edmx o .dbml y borrar y volver a crear el DomainService. Una vez que usted ha terminado, haga clic en el menú “Tools” en Visual Studio y seleccione MetadataAddin.

El Addin va a hacer un ciclo a través de todos sus proyectos en sus soluciones y todas sus carpetas en sus proyectos. Básicamente, se busca todos los archivos “.metadata”. Una vez que se encuentra el archivo, se crea un diccionario de los tipos de objectos expuestas a través el MetadataTypeAttribute. A continuación, busca cualquier “EntityCollection” o cualquier objecto que contenido en el diccionario como propiedades y agrega el [Include()] atributo.

Por último, he añadido el código que nos avisa cuando se termina la operación.

Cuando el proceso ha terminado todos sus archivos “.metadata” se cargarán y se podrá revisar los cambios realizados en los archivos.

Aquí está el link para el proyecto de ejemplo. He incluido un archivo README.txt en el proyecto para indicarle dónde debe poner el “Add-in”.

Espero que esto ayude!

Visual Studio Add-in for Domain Service [Include()] attribute

November 10, 2010 5 comments

Sometimes you don’t have the luxury to develop your applications from a domain centric approach. This means that you need to do reverse engineering of your datamodel and create your entities from it. Luckily we have either the Entity Framework or Linq2Sql to help us out. Since we are targeting Silverlight, we are still not finished as we need to use WCF RIA Services to transport our changes back and forth from the server.

An issue I have with the current workflow when using WCF RIA Services is that anytime the database model changes, we need to do several things:

  1. Update the Entity Framework (.edmx) or Linq2Sql (.dbml) file with the datebase schema changes.
  2. Drop the DomainService that you have created which includes the service file and the .metadata file.
  3. Build the Web project that is hosting your model.
  4. Add a DomainService again.
  5. Add all of the [Include()] attributes into the .metadata file.

Right now this is a very painful experience and whenever I can automate this I will do so. This leads us to the purpose of this post which is a way to at least automate the adding of the [Include()] attribute on the .metadata file. The solution to this was originally posted here and I have modified it slightly to support recursive folders and to work on Visual Studio 2010 RTM.

I created a new solution and selected Extensibility under the “Other Project Types” and then “Visual Studio Add-in” as seen below:

The project template will the create what is shown below except for the MetadataHelper.cs file.

Take some time to review what is in place in the Connect.cs file as well since there is some custom logic to get my MetadataHelper.cs file working correctly.

Basically the purpose of this Add-in is to allow you to update your .edmx or .dbml file and the drop and re-create your DomainService. Once you have done that you will click on the Tools menu in Visual Studio and then select MetadataAddin.

This will cycle through all of your projects in your solutions and all of your folders in your projects. It basically is looking for any .metadata files. Once it finds the file it builds a dictionary of the types of entities exposed through the model by looking for the MetadataTypeAttribute. It then looks for any “EntityCollection” properties or any types that were stored in the dictionary as properties and adds the [Include()] attribute.

Finally, I added code to popup a message box letting me know that it has “Finished executing”.

When the process has finished all of your .metadata files will be loaded and you will be able to review the changes made to the files.

Here is the link to the sample project. I included a README.txt file in the project to show you where you need to put the Add-in once you have successfully built the project.

Hope this helps!