I am working on a project utilizing MVC4 and EF Data First in VS2012. The table has a primary key which does not have "id" in the field name so EF does not understand it should use it as the primary key. After EF generates the code I add the following annotations and using statements.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public partial class Game
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int GameNumber { get; set; }
If I base my models from the generate code the custom changes I make will be discard if I update the database models. How can I keep my custom changes and update the database EF data model.
Thanks
use MetadataTypeAttribute (MSDN) to define a metadata class on a partial implementation of your entity class, then decorate the properties in that metadata class.
Note that the decorated partial class implementation should exist in a file other than the autogenerated file so as to persist refreshing from DB.
(question: if your model is DB first, why doesn't it know what the PK is for the Game table? Whether or not the property has Id at the end doesn't matter when it's reading the table schema to generate the model...)
[MetadataType("GameMetadata")]
public partial class Game
{
public class GameMetadata
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int GameNumber;
}
}
Related
I'm writing a web app using Core 2.0 MVC. With the help of EF I'm trying to create (code first) models to model the database so I can automate the whole db creation process using migration.
My issue, I'm using a third party library to interact with an API (this library was built specifically to interact with this API) but the data that the API returns I'd like to store in a db using the same schema as the class from the library.
As an example
Third party library
public class PersonDetails
{
public long PersonID { get; set; }
public string PersonName { get; set; }
}
If i try to create a migration for this class it complains about no primary key being set, I'm unable to modify this class. Is there a way that I can set the [Key] attribute for PersonID from an inherited class or something similar?
I'm facing some problems working with EF DB First. Say I've got:
A table Person
A table Student with a foreign key pointing to Person
A table Teacher with a foreign key pointing to Person
The model created from the database generates the next classes:
public class Person{
this.Student= new HashSet<Student>();
this.Teacher= new HashSet<Teacher>();
}
public class Student{}
public class Teacher{}
And what I'd really like to see is
public class Person{}
public class Student:Person{}
public class Teacher:Person{}
Is there any convention over configuration or anything I'm missing to get the inherited classes ?
UPDATE
Classes are generated in such a way because the model specifies these associations between Person, Teacher and Student. My question should be then...Is there any way to create a model from a DB using EF so that the model contains classes that inherit from other ones?
You're looking for Table-per-Type (TPT) mapping. Try the solution here:
Entity Framework DB-First, implement inheritance
I am following along Pro ASP.NET MVC 4 by Adam Freeman on VS 2010 (I downloaded the MVC 4 template online). I have worked with the .edmx file before, but in Chapter 7 he does not do this. I setup a basic connection string with SQL Server in my web.config file within my WebUI project where my controllers and views are located. Also, I listed my Domain classes within my Domain project below. The problem comes when I run the application. The application is not recognizing my table in my database (dbo.Request) and instead is creating a table based on my class name in the Entities namespace (so it creates a CustRequest table) and it also creates a _Migration_History table. To prevent this I add the Data Annotation above my class [Table("MyTableName")]. I could not figure out why I had to add this Data Annotation. Also, EF made me add a [Key] above my primary key, which i can understand because i do not have an ID property, but in the book he did not do this. I was wondering if I was missing something obvious as I am pretty new to MVC. Any help would be appreciated. I am working with EF 6. Thank you.
namespace Requestor.Domain.Entities
{
[Table("Request")]
public class CustRequest
{
[Key]
public int RequestId { get; set; }
public string RequestByUserCd { get; set; }
public DateTime RequestDateTime { get; set; }
public DateTime DueDate { get; set; }
}
}
namespace Requestor.Domain.Abstract
{
public interface ICustRequestRepository
{
IQueryable<CustRequest> Request { get; }
}
}
namespace ITRequestHub.Domain.Concrete
{
public class EFDbContext : DbContext
{
public DbSet<CustRequest> Request { get; set; }
}
}
namespace ITRequestHub.Domain.Concrete
{
public class EFCustRequestRepository : ICustRequestRepository
{
private EFDbContext context = new EFDbContext(); //retrieves the data
public IQueryable<CustRequest> Request
{
get { return context.Request; }
}
}
}
Consider trying again with EF5 if you can, I experienced similar issues when trying to make EF6 work with MVC4 (I couldn' make scaffolding work either).
Or go all the way up to the latest versions for everything and try MVC5 with EF6 (this seems to work fine)
You've run into the wonderful and sometimes frustrating part of EF, its conventions. Wonderful when you're aware of the conventions as they simplify life, but frustrating when you feel that the framework is performing tasks without your explicit permission.
Firstly, additional information on EF6 conventions can be found here: http://msdn.microsoft.com/en-gb/data/jj679962.aspx
On your first point, as far as I'm aware, EF takes the name of your entity as the name of the table it will create in your DB. As you've discovered, you do have control over this via the "Table" attribute, but you can also control it's desire to want to pluralize your entity names when creating tables by means convention removal within your DbContext
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>()
On your second point, I cannot imagine that you would require a "Key" attribute attached to your "RequestId" field. The convention here is that if the field name contains a suffix of ID (case-insensitive), then EF will automatically include it as a primary key and if the type of the field is either an Int or a Guid it will be automatically set as an auto-seed identity column.
I am curious as to why data validation is done using buddy classes. Consider the following example, where MyEntity is a Linq-to-SQL or Linq-to-Entities entity, and the class below is a partial class enhancing the entity.
[MetadataType(typeof(MyEntity.MyEntityMetadata))]
public partial class MyEntity
{
private class MyEntityMetadata
{
[Required(ErrorMessage = "The title is required.")]
public string Title { get; set; }
}
}
Why is the design so? When they designed DataAnnotations, why was this "buddy pattern" selected? Why not place the attributes directly in the entity?
I assume this prevents generated entities from overwriting custom Meta Data information.
The reason is practical - in linq-to-sql and linq-to-entities, the code representing the classes regenerated every time the object model is updated. In order for the annotations not to be overwritten when this happens, they need to be in a separate "buddy" class.
If you're using Data Annotations in a different context - say for a view model - then they can go on the original class itself.
We're throwing together a quick project (CRUD forms) and decided to skip view models and use EF entities directly in controllers and views. Since I'm not used to this approach, I'm confused about handling validation.
For example: a DB field has a length of 25. How does that get transferred (if it can) to a validation constraint in my view? If i was using an intermediate model, I would attach attributes to the model properties and it would work. How would I do this using EF objects directly? Thanks.
This can be done using MetadataType attribute on the Ef generated classes. The EF generates partial classes. So those can be extended and attribute added to it. Then another "buddy class" can be written that can have member decoration. For example
[MetadataType(typeof(EFGeneratedClass_MetaData))]
public partial class EFGeneratedClass
{
}
public partial class EFGeneratedClass_MetaData
{
[Required]
[Display(Name="Member1 Display")]
public string Member1 {get; set;}
}
Easiest thing to do is to use the DataAnnotations attributes that are in the System.ComponentModel.DataAnnotations anmespace.
MVC respects those and will populate your ModelError collection if any fail. In the case of your example, you could add a using statement for that namespace and then just flag a property with
[StringLength(25)]
and call it a day.
You need to use a partial 'buddy' meta class and decorate it with validation attributes.
For example, say your entity was 'Foo':
[MetadataType(typeof(FooMetadata))]
public partial class Foo {}
public class FooMetadata
{
//apply validation attributes to properties
[Required]
[Range(0, 25)]
[DisplayName("Some Neato Property")]
public int SomeProperty { get; set; }
}
For more information see this link on MSDN:
Customize Data Field Validation in the Model
Cheers.