Use T4 DBContext Script to Write Display Name Attribute - entity-framework

My issue is simple: the code I'm writing is in English, but the interface is in Portuguese. Not a problem, as I can do this:
[Display (Name = "Símbolo")]
public string Symbol { get; set; }
This way, when I render my screen, it comes in Portuguese:
#Html.LabelFor(model => model.Symbol)
But...
As I am using Model First EF for my project, classes are constantly been changed by a T4 DbContext Generator. That way I can't use Display attribute, as it will be overwrited.
A solution given here is to extend partial classes automatically created. Kinda clumsy for me.
So my idea is to change the T4 script to get Documentation.Summary attribute from the EDMX model and add it as a Display Name attribute.
I found an article where someone explains how to extract this data, but I'm not succeding in making it work on DbContext Generator.
Has someone ever made this? Do you guys have better ideas?
Thanks!

Related

Can I replace some of this with the Fluent Api?

Say I have the following property in a class (where I'm using Code First):
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
I'd rather not decorate my Password property with these annotations. I'd rather use the Fluent Api if possible. How many of these annotations could be done using the Fluent Api? I know Required can be, and StringLength. But I don't know about ErrorMessage, DataType and Display.
I take the View:
a)Decorate the POCO with genuinely useful business constraints. MVC and EF amongst others will check a few of the important constraints for You.
b) You can and should add checking for custom Annotations or other business rules to the POCO.
see sample bloew if interested:
c) DB specific annotations belong in EF fluent API. If they are DB specific that dont belong on the POCO in my view. Eg Table name, schema, Foreign key, association maps, column renames and ignores etc.
d) Error messages and Display texts belong on the Model View.Or at least abstracted from teh POCO example below. I know people dont like double effort and will use POCO as Model views and like easy text and error message handling. But I prefer a full error message/text handling solution that is multi-lingual and configurable. Sticking texts on a POCO, isnt the best solution in my view.
Clearly style and build size influence the choice and many will disagree with d) and I dont have a big issue with that . Im taken a big picture design pattern view and look to separate and abstract where it makes sense.
here a little POCO extra sample, not with annotations but it could have been. I have seen some nice examples with annotations as well. This style of error can be used in MVC and is better than texts in annotations in my view.
public class POCODemo : IValidatableObject //various ways to trigger this. Some for free
/// poco members .... bla bla
//Support Business rules...
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var vResult = base.Validate(validationContext).ToList();
if (Poco.property1 || poco.property is nasty or xyz issue)//psuedo code for your check
var memberList = new List<string> { "PropertyName1" };
var err = new ValidationResult("Some Text comes from your TEXTPOOL of choice that explains the error", memberList);
vResult.Add(err);
// }
}
return vResult;
}
I know Required can be, and StringLength.
And that's all.
Keep in mind that the same attributes can be used by different "frameworks" and for very different purposes. If you use - for example - the Required attribute in a context of ASP.NET MVC it will be used for MVC model validation - on client side by some Javascript injected into the page or on server side to set ModelState.IsValid.
The Required attribute is also used by Entity Framework Code-First to validate an entity, but this has actually nothing to do with the MVC model validation. If you replace the Required attribute by configuration with Fluent API you still influence Entity Framework, but for ASP.NET MVC you just have removed the attribute, i.e. the property is not required anymore for MVC validation. ASP.NET MVC doesn't care about Entity Framework's Fluent API.
The same is true for StringLength. ErrorMessage, DataType and Display play no role with Entity Framework, neither as attributes nor are there counterparts in Fluent API.

EF5 Database first model templates (tt) for class generation

I want to make that all my Entities created form an existing database inherits from the same interface.
I suppose this can be done through the templates. And I've seen that ugly .tt file, but there is no help (or I haven't found it).
There are any documentation, examples, ... of the templates?
There are any tips or pre-made templates for common paradigms, for example N-Layer Design or Domain Driven Desing?
Look for "T4 Templates". That will give you introduction to T4 Templates (.tt files).
With a bit of searching you can easily extend this template to your needings. I did this myself already, but with a template from EF4. I don't know if the templates differ.
I made a little helper functions for this:
string Interfaces(EntityType entity)
{
string interfaces = string.Empty;
if (entity.Members.OfType<EdmProperty>().Any(edmProperty => edmProperty.Name == "Guid" && ((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.Guid))
{
interfaces += ", IHasWritableGuid";
}
return interfaces;
}
The part where the template writes the actually entity class (this differs for sure in the new template) is somewhat below "Write EntityType classes." in the EF4 template.
<#=Accessibility.ForType(entity)#>
<#=code.SpaceAfter(code.AbstractOption(entity))#>
partial class
<#=code.Escape(entity)#> :
<#=BaseTypeName(entity, code)#>
<#= Interfaces(entity) #>
Here I just added a call to my interfaces method.
I know this is not the exact answer, but it should give you help with editing the template file yourself. Just bite yourself through it. :)

What is the best way to prevent updating on specific fields in Entity Framework

Im writing an web application with MVC using Entity Framework for my backend logic. My problem is that I have an entity that has certain fields that should never be changed on an update. I am not really sure what the best way to solve this problem would be. There is going to be a lot of data processed in my application, so I cant afford to just hack up a solution.
Is it possible to just define the fields as readonly in the POCO entities ? Or should I write and entity framework extension class that validates all updates. Could it be done in the mapping files between EF and the actual database?
I am relatively new with EF, so I hope some of you might be able to give me some pointers!
Thanks!
If you are using .NET 4.5 and EF 5 (i.e. MVC 4), you can simply set IsModified = false on the individual properties in question. This has the benefit of sticking close to the default out-of-the-box MVC conventions.
For example, if you have a CreatedBy field that shouldn't be touched when the record is updated, use the following in your controller:
[HttpPost]
public ActionResult Edit(Response response)
{
if (ModelState.IsValid)
{
db.Entry(response).State = EntityState.Modified;
db.Entry(response).Property(p => p.CreatedBy).IsModified = false;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(response);
}
Note that the IsModified line is the only change from the default controller action.
You MUST put this line AFTER setting .State = EntityState.Modified (which applies to the record as a whole and adds the record into the db context).
The effect is that EF will not include this column in the SQL UPDATE statement.
I am still (very) shocked that there are no [InsertOnly] or [UpdateOnly] attributes similar to [ReadOnly]. This seems like a major oversight by the MVC team. Am I missing something?
I'm not fully satisfied with this solution because it's a hack: You're telling EF that no change was made when what you really mean to say is "HANDS OFF". It also means that you have to use this code anyplace where the field could be updated. It would be better to have an attribute on the class property.
(Apologies for posting to an older thread, but I've not see this solution anywhere else. ViewModels are robust but a lot of work, and EF was supposed to make things easier, not harder...)
Well I would advice against ever using the EF classes in the View. You're best bet is to construct ViewModel classes and use Automapper to map them from the EF classes.
When you are updating records in the database though, you can control which fields in the ViewModel are used to update the existing fields in the EF class.
The normal process would be:
Use the Id to get the latest version of the existing object out of the database.
If you are using optimistic concurrency control then check that the object has not been updated since the ViewModel was created (so check timestamp for example).
Update this object with the required fields from your ViewModel object.
Persist the updated object back to the database.
Update to include Automapper examples:
Let's say your POCO is
public class MyObject
{
public int Id {get;set;}
public string Field1 {get;set;}
public string Field2 {get;set;}
}
and Field1 is the field you don't want updating.
You should declare a view model with the same properties:
public class MyObjectModel
{
public int Id {get;set;}
public string Field1 {get;set;}
public string Field2 {get;set;}
}
and Automap between them in the constructor of your Controller.
Mapper.CreateMap<MyObject, MyObjectModel>();
you can if you wish (although I prefer to do this manually, automap the other way too:
Mapper.CreateMap<MyObjectModel, MyObject>().ForMember(dest=>dest.Field1, opt=>opt.Ignore());
When you are sending date to your website you would use:
var myObjectModelInstance = Mapper.Map<MyObject, MyObjectModel>(myObjectInstance);
to create the viewModel.
When saving the data, you'd probably want something like:
public JsonResult SaveMyObject(MyObjectModel myModel)
{
var poco = Mapper.Map<MyObjectModel, MyObject>(myModel);
if(myModel.Id == 0 )
{
//New object
poco.Field1 = myModel.Field1 //set Field1 for new creates only
}
}
although I'd probably remove the exclusion of Field1 above and do something like:
public JsonResult SaveMyObject(MyObjectModel myModel)
{
var poco;
if(myModel.Id == 0)
{
poco = Mapper.Map<MyObjectModel, MyObject>(myModel);
}
else
{
poco = myDataLayer.GetMyObjectById(myModel.Id);
poco.Field2 = myModel.Field2;
}
myDataLayer.SaveMyObject(poco);
}
note I believe that best-practise would have you never Automap FROM the ViewModel, but to always do this manually, including for new items.
I just asked a very similar question, and I believe the answer to that one may help out a lot of folks who stumble across this one as well. The OP mentions that these are fields that should never change, and using PropertySaveBehavior.Ignore ensures this. With the existing answers to this question, you need to make custom save methods or introduce mapping where it might not make sense. By setting the AfterSave property behavior instead, you can prevent this from being possible in EF altogether.
In my project, I am generically accessing a property that is on an abstract class so I have to set it like this:
MyProperty.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
If you're accessing it directly on a known class, you'd use this:
...
.Property(e => e.YourProperty)
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);

Ignoring an required field of an entity

I got the following variable into my entity:
[DataType(DataType.Currency)]
[DisplayName("Value U$:")]
[Required(ErrorMessage = "Currency Required.")]
public decimal? CurrecyValue { get; set; }
Actually Im using this entity and I dont need this field. As soon as I post any information the ModelState becomes invalid because its required.
I know that I can use ModelState.Clear(); but, doing this I'll ignore all the other validations that I need.
Is there any way to just ignore this specific field without clearing my whole ModelState ?
Thanks !
Ugly and totally not recommended workaround:
ModelState.Remove("CurrecyValue");
Recommended solution:
Use view models. But real view models. Not some hybrids which you call view models and into into which you stick your domain entities and which you wonder how to get rid of simply because they are not adapted to the requirements of the given view. You should define a specific view model for each of your views. If you don't follow this very simple rule you will struggle a lot with ASP.NET MVC.

Meta data on table scaffolding in dynamic data project

I created an ASP.NET webapplication with dynamic data. I'm fairly new to this so I'm struggling with alot of things but now I'm completely stuck.
Thing is, I want to hide, lets say, the name column of a table in my database (model based on entity framework). Therefor I added a new folder named "AppCode" (because I cannot add the default app_code folder in a web app) and added a file named "User.cs" The contents of this file look like this:
[MetadataType(typeof(UserMetaData))]
public partial class User{
}
public class UserMetaData
{
[ScaffoldColumn(false)]
public object Name;
}
Now, after running the application I did not expect to see the name column in the crud pages, but it is still there. What am I missing here?
Thanks alot.
Finally figured it out myself. What went wrong was the fact that my model was placed in a referenced class library and not in the dynamic data project itself. It seems to be very important that the namespace of the partial class is the same as that of the model. Otherwise it would not work. So, in my case I had to place the partial class in my "domain" project which contains the model. Hope this helps someone.