ADO.NET Entity Data Model auto generated code violates Code Analysis CA2214 - entity-framework

In a MVC 3 solution, under VS 2012, it sounds strange that you receive such message after Running Code Analysis:
It is strange because the class which is mentioned in the "DON'T" analysis was generated by VS itself (not me).
To reproduce this you can:
add ADO.NET Entity Data Model to your solution,
add your database tables (already existent in SQL Server) to your diagram,
rebuild solution, add Controllers and cshtml views (those ones are generated automatically).
run the code analysis from ANALYZE menu.
So, the question is, what could we do: Refactor the auto-generated code or ignore this message?
Below a sample of auto generated class which violates the rule CA2214:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Backoffice.Entities
{
using System;
using System.Collections.Generic;
public partial class BR_SIMUL_Supermarket_Product
{
public BR_SIMUL_Supermarket_Product()
{
this.BR_SIMUL_Supermarket_Product_Price = new HashSet<BR_SIMUL_Supermarket_Product_Price>();
}
public int product_id { get; set; }
public int category_id { get; set; }
public string product_name { get; set; }
public string product_measure { get; set; }
public bool product_active { get; set; }
public virtual BR_SIMUL_Supermarket_Category BR_SIMUL_Supermarket_Category { get; set; }
more stuff here...

Here's how I solved it permanently: http://chuckbeasley.com/blog/?p=42200

This is by design to allow for lazy loading. When you access the classs through DbContext it won't fail at run-time despite the warning. You should suppress the warnings only in those files.

You should feel free to suppress these. Take a look at this discussion on the Entity Framework codeplex site for more details.

Related

Customization for autogenrated index view not working

I am using MVC 4.0 and entity-framework 5 to generate model.
I m trying to understand concept of customization, i followed same steps given in tutorials site like this and this
only difference is I am adding this customization class code in different sub folder because when directly try to add this in model folder it shows error employee class already created in this ( autogenrated by entity framwork)
Auto generated code By Entity Framework
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CustomizationConceptUmang.Models
{
using System;
using System.Collections.Generic;
public partial class employee
{
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
}
}
Code for customization
namespace CustomizationConceptUmang.Models.ViewModel
{
[MetadataType(typeof(employeeMetaData))]
public partial class employee
{
}
public class employeeMetaData
{
[Display(Name="Employee Name")]
public string name { get; set; }
}
}
View
<th>
#Html.DisplayNameFor(model => model.name)
</th>
Still it showing name instead of Employee Name
please suggest me how to resolve this Thanks in advance.
The partials are in different namespaces, so they're two separate classes and the metadata is not applied to the employee entity.
Match up the namespace to combine multiple partial classes into one.
Anyway don't use Entity Framework models as viewmodels. Create a separate class with annotations for a viewmodel, and map to and from your entity. You'll thank me later.

Database First Validation

I have an auto-generated Entity Framework model. It was generated using a database first approach. The mid_initial column has a database defined constraint that limits the column to a maximum length of 3 characters.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Agency.DataAccess.RegistrationModel
{
using System;
using System.Collections.Generic;
public partial class Registrant
{
public Registrant()
{
}
public int id { get; set; }
public string fname { get; set; }
public string mid_initial { get; set; }
public string lname { get; set; }
}
}
When I try and create a model with a mid_initial greater than 3 characters, a invalid state, ModelState.IsValid is returning true. Because of this db.SaveChanges is then called, which then raises DbEntityValidationException.
[HttpPost]
public ActionResult Create(Registrant registrant)
{
try
{
if (ModelState.IsValid)
{
Debug.WriteLine("Entity was valid.");
db.Registrants.Add(registrant);
db.SaveChanges();
return RedirectToAction("Index");
}
return View("Create", registrant);
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Debug.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Debug.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
return View(registrant);
}
}
Why is the ModelState.IsValid method returning true? It would seem that my model is not aware of the maximum length constraint. How do I make it aware?
EF db-first can't infer constraints from database.
Use the MaxLenght data annotation attribute:
public partial class Registrant
{
public Registrant()
{
}
public int id { get; set; }
public string fname { get; set; }
[MaxLength(3, ErrorMessage = "")]
public string mid_initial { get; set; }
public string lname { get; set; }
}
Note: this class is a auto generated class and every time you update and save your model (.EDMX file), this code will be overwritten and you'll loose your attributes.
To avoid that, you should extend your classes with some partial classes with the same name and same namespace as your auto-generated classes. If you need examples to show you how, tell me to put it in answer.
MVC is EF-agnostic, and as such doesn't implicitly attempt to validate the model using EF validation to populate its ModelState.
You have four basic solutions I can think of right now:
Hook them up yourself, for example using MVC filters, DbContext.GetValidationErrors and ModelState.
Find and use third-party code that does this already.
Validate the code separately using facilities that MVC can use, for example using DataAnnotations. You may try to generate them automatically by modifying the EF T4 template. Note that this is still technically redundant (the code will be validated twice, once by MVC, once by EF).
Submit a patch for MVC so that it can support EF explicitly (as a soft dependency) and make it all just work (both projects are open source) -- or downvote me because they already did so and I never knew it.

ef5 database first data annotation

I am starting MVC4 with VS2012. I am also using EF5 with the "Database First" method of creating my classes.
However because the generated glasses can be regenerated I cannot put the Data Annotation details to assist with validation.
I have seen some code snippets that use MetaData and partial classes but I was wondering if anyone knows of a small compilable example that I can look at and pull apart to better understand how the vasious classes interlink.
Many many thanks for any help.
Dave
You can achieve what you need through extending models. Suppose that EF generated the following entity class for you:
namespace YourSolution
{
using System;
using System.Collections.Generic;
public partial class News
{
public int ID { get; set; }
public string Title { get; set; }
public int UserID { get; set; }
public virtual UserProfile User{ get; set; }
}
}
and you want do some work arounds to preserve your you data annotations and attributes. So, follow these steps:
First, add two classes some where (wherever you want, but it's better to be in Models) like the following:
namespace YourSolution
{
[MetadataType(typeof(NewsAttribs))]
public partial class News
{
// leave it empty.
}
public class NewsAttribs
{
// Your attribs will come here.
}
}
then add what properties and attributes you want to the second class - NewsAttribs here. :
public class NewsAttrib
{
[Display(Name = "News title")]
[Required(ErrorMessage = "Please enter the news title.")]
public string Title { get; set; }
// and other properties you want...
}
Notes:
1) The namespace of the generated entity class and your classes must be the same - here YourSolution.
2) your first class must be partial and its name must be the same as EF generated class.
Go through this and your attribs never been lost again ...

EF code first circular reference

I have a question about Entity Framework.
In our project we would need to have some circular references, like this one:
public class OptionClusterSet
{
public int ID { get; set; }
public virtual ICollection<OptionCluster> OptionClusters { get; set; }
}
public class OptionCluster
{
public int ID { get; set; }
public long OptionClusterSetId { get; set; }
public virtual OptionClusterSet OptionClusterSet { get; set; }
}
The thing is that whenever we try to, for example, get a OptionClusterSet including its OptionClusters using eager loading, the OptionClusters try to load their OptionClusterSets and so on. So we get an infinite loop.
Is there a way to configure this so it works properly?
It works properly out of the box unless you try to serialize it - serialization needs some special handling (attributes) to let serializer recognize circular reference.
Eager loading loads only the level you specify in Include call, nothing more. Everything else can be loaded through lazy loading but EF don't load again the relation which was already loaded. There are some scenarios when it doesn't work as expected - the example is navigation property fixup in POCO generator (it lazy loads additional data to fixup the reverse navigation property).

How can I have Entity Framework return related objects with some defaults?

Say I have Project and Task EF Code first classes
public class Project
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
}
public class Task
{
public int ID { get; set; }
public string Name { get; set; }
public int ProjectId { get; set; }
public bool IsDeleted {get; set;}
public virtual Project Project { get; set; }
}
Say I have
public void SomeAction()
{
Project p= repository.GetById(1);
var tasks = p.Tasks;
//var tasks = p.Tasks.Where(t=>t.IsDeleted==false);
}
I would like that my Tasks property on the Project class will always perform that filter on IsDeleted and just return that subset ... to avoid having to write that condition all over the place...
Any recommendations?
Edit:
Im using EF Code First
Add a discriminator to your model in the OnModelCreating method
modelBuilder.Entity<TEntity>().Map(m => m.Requires("IsDeleted").HasValue(false));
Caveats
You can no longer load deleted items (unless you map IsDeleted true to another entity, then you may lose your automatic filtering)
The poco class cannot have the IsDeleted property (discriminators cannot be mapped)
because the IsDeleted cannot be mapped you need to run raw SQL to delete the entity in the first place.
EF Code first = NO WAY. Just one from long list of features which is available in EDMX and it is completely missing in code first. Mapped condition from EDMX does this but it is still problematic because it is hardcoded and cannot be changed (= you will never be able to load deleted entities even if you want to unless you use another EDMX). The solution would be implementation of global filters in EF but EF doesn't have anything like that despite the fact that old Linq-to-entities have them at least for relations (DataLoadOptions.AssociateWith).
This is much more painful in relations where you cannot use eager or lazy loading without loading deleted entities to your application as well and do filtering in your application's memory.
In the Model Designer, select your Task entity, and bring up the Mapping Details window. This should show you the database table your entity is mapped to, and all the columns. Just under where it says "Maps to [YourTable]" you should see an option <Add a Condition>. This should let you set a condition like what you're looking for.