Tweaking Model EF Models removes Annotations ....

Sep 23, 2012 at 1:34 AM

Hi,

This is an EF/MVC issue, but would effect NO as well I suspect. I have been experimenting with the  Model First EF with the EF5 DBContext generator which creates the DBCOntext class and the POCO classes. One then adds validation annotations to these domain classes. Unfortunately when one adds say a new column to the model and migrates the DB, the POCO class is regenerated losing all the annotations. The only way around this I have heard about is to create a "Metatype" "buddy class". However as far as I can see one has to manually keep this in step with the original domain class.

I realise that NO has its own T4 generator for the POCOS, but I am wondering whether the same issue exists with NO?

Thoughts...


Thanks.

Editor
Sep 23, 2012 at 10:00 PM


On 23 September 2012 01:34, ESSB <notifications@codeplex.com> wrote:

I realise that NO has its own T4 generator for the POCOS, but I am wondering whether the same issue exists with NO?

Yes, it does... and a metadata class is the recommended solution. As you say, this is an EF thing.

Dan

PS: next version of NO MVC will have improved code first support, though - again, an EF thing - code first and model first have differing capabilities.

Sep 24, 2012 at 12:49 AM

Dan,

Thanks for this. I have now got the meta buddy class mechanism working nicely.

I have to say that I am a visual modelling fan, so prefer Model-First with the new Model-> DB Migration script generator. However this does not work in VS2012, so I have to stay with VS2010, until it is implemented. There was a concern that MS was depracating MF in favour of CF. The latter is certainly getting development time, but MF and DF are not being depracated thankfully.

Thanks,

Ed

Sep 26, 2012 at 5:45 PM

The documentation suggests an alternate approach:

(copied from the documentation)

If you make any subsequent change to the entity model (as you will, many times, in a typical project) and you run the T4 template, then you will over-write any modifications that you have made to the previous generated version - such as methods or attributes that you may have added.

One approach, recommended my Microsoft is to place all your own logic in a separate partial class, and to use a 'buddy class' to add any attributes to properties. Alternatively, we recommend that having generated your classes, you copy them into a separate and then exclude the template until it is needed again. If the classes need to be generated again then repeat the process, and use a 'diff' tool to merge in any changes.

Editor
Sep 26, 2012 at 5:48 PM
Yeah, I think that is what Richard uses. I prefer the buddy class approach myself.

Dan

On 26 September 2012 17:45, dmoss <notifications@codeplex.com> wrote:

From: dmoss

The documentation suggests an alternate approach:

(copied from the documentation)

If you make any subsequent change to the entity model (as you will, many times, in a typical project) and you run the T4 template, then you will over-write any modifications that you have made to the previous generated version - such as methods or attributes that you may have added.

One approach, recommended my Microsoft is to place all your own logic in a separate partial class, and to use a 'buddy class' to add any attributes to properties. Alternatively, we recommend that having generated your classes, you copy them into a separate and then exclude the template until it is needed again. If the classes need to be generated again then repeat the process, and use a 'diff' tool to merge in any changes.

Read the full discussion online.

To add a post to this discussion, reply to this email (nakedobjects@discussions.codeplex.com)

To start a new discussion for this project, email nakedobjects@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Sep 26, 2012 at 6:06 PM

I know ESB alredy has it figured out, but for anyone else, the documentation also includes an example of how to set up a buddy class.

(copied from documentation)

// This partial class has been generated automatically from the entity model
// and is not touched by the application programmer.
// It contains all the properties for Product.
public partial class Product {
 
  public virtual int Id { get; set; }

  public virtual string Name { get; set; }
  
  public virtual int UnitsInStock { get; set; }
}

//Use this partial class to define actions for the Class1 class.
//Also for methods to enrich the behaviour of properties - such as Validate,
//Default, or Choices and for class-level attributes such as <IconName>.
[MetadataType(typeof(Product_Metadata)]
[IconName("Package.png")]
public partial class Product {

  public void RecordReceiptOfNewStock(int Number) {...}

  public string ValidateName(string value) {...}
}

//This is the so-called 'buddy class' for Class1.  It should have the same
//properties as the auto-generated partial Class1 class, to which attributes
//property-level attributes such as <Hidden> may be added.
public class Product_Metadata {
 
  [Hidden]
  public virtual int Id { get; set; }

  [StringLength(25)]
  public virtual string Name { get; set; }
 
  [Disabled]
  public int UnitsInStock { get; set; }
}

Coordinator
Sep 27, 2012 at 9:37 AM

Yes  -  I don't like the 'buddy class' approach  -  I find that it creates as many code maintenance issues as it purports to solve.  But its purely a personal choice.

Three years ago, on a visit to Redmond, I was told that the buddy class pattern was a kludge, because the EF team couldn't get the change to the .NET that they really wanted implement by the languages group in time for .NET 3.5.  I infer that what they wanted was language support for 'partial properties' so you could have something like this: 

//My code
public partial class Foo {

 [Annotation]
 public partial string Bar

}

//Generated code
public partial class Foo { 

 public partial string Bar { get; set;}

}
I think they must have then forgotten the idea (perhaps with the increased emphasis on Code First) for the subsequent .NET releases.  This would have been much better   -  though I might still have opted for the single class approach personally.