I'm using standards for singular table names. EF4 Code First has by default to pluralize table names. I have put the code to override this convention, but seems is not working.
using section:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Database;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Conventions.Edm;
Data context:
public class SiteDataContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<BlogFeedback> BlogFeedbacks { get; set; }
public DbSet<BlogCategory> BlogCategories { get; set; }
// Twist our database
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
Tables created:
Blogs
BlogFeedbacks
BlogCategories
When because the convention override (and what I need) should be:
Blog
BlogFeedback
BlogCategory
Anyone has an idea why the override line is not working? Thanks a lot.
Your using the wrong convention. You need to do the below.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
I our current project we had the same problem. I wrote about it in another question, but here it is:
Entity Framework v4 and underscores in column names
It's a little more complex than expected.
HTH
Related
I am trying to enable migrations for data entity: In Package Manager Console:
Enable-Migrations -ProjectName Vidly -ContextTypeName Vidly.Models.MyDBContext
I get:
Code First Migrations enabled for project Vidly.
Then
add-migration 'InitialModel'
I get: "The project 'Vidly' failed to build."
My Configuration.cs:
namespace Vidly.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<Vidly.Models.MyDBContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(Vidly.Models.MyDBContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data.
}
}
}
And my MyDBContext.cs is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace Vidly.Models
{
public class MyDBContext
{
public DbSet<Customer> Customers { get; set; } // My domain models
public DbSet<Movie> Movies { get; set; }// My domain models
}
}
The error message is:
error CS0311: The type 'Vidly.Models.MyDBContext' cannot be used as
type parameter 'TContext' in the generic type or method
'DbMigrationsConfiguration'. There is no implicit reference
conversion from 'Vidly.Models.MyDBContext' to
'System.Data.Entity.DbContext'.
It seems I cannot use MyDBContext as a type super class in Configuration.cs.
Please help. Thanks.
You are missing to implement DbContext.
Change AND try:
public class MyDBContext:DBContext
{
public MyDBContext() : base("ConnectionStringName")
{
}
public DbSet<Customer> Customers { get; set; } // My domain models
public DbSet<Movie> Movies { get; set; }// My domain models
}
Couple of things you are missing here.
Inheriting from DBContext
Constructor to pass the name of connection string entry you used in
use below snippet of code. note: replace VidlyDBConnectionString with your connection string name
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace Vidly.Models
{
public class MyDBContext :DbContext
{
public MyDBContext():base("name=VidlyDBConnectionString")
{
}
public DbSet<Customer> Customers { get; set; } // My domain models
public DbSet<Movie> Movies { get; set; }// My domain models
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace Vidly.Models;
{
public class MyDBContext :DbContext
{
public DbSet<Customer> Customers { get; set; } // My domain models
public DbSet<Movie> Movies { get; set; } // My domain models
}
}
In an MVC Project, I have a Page class and a Container class. I'm intending for each to have their own table in the database, so for each page, there will be a list of containers to choose from. A Page can have multiple containers and a single container can be used on multiple pages.
My problem is, I don't want anything to be stored in the Container class regarding the page it is on. A Page contains the the Containers but from the Container class, the page is is found on is irrelevant.
All of the Entity Framework examples I have seen for this type of relationship seem to store a foreign key on both classes.
public class Page
{
public int Id { get; set; }
public virtual ICollection<Container> Containers {get;set;}
...
}
public class Container
{
public int Id { get; set; }
public virtual ICollection<Page> Pages{get;set;}
...
}
Any help would be greatly appreciated. I've been stuck trying to find the correct way to do this for a few days.
Thanks.
I don't want anything to be stored in the Container class regarding the page it
is on.
This is simply a difference between OO modeling and relational modeling. In a pure OO model you can have a property of type
class Foo
{
List<Bar> Bars = new List<Bar>();
}
And the Bar objects don't have any knowledge about the Foo object. But the relational model simply doesn't work like that. Relationships are all implemented with foreign keys. So in the database foreign keys are required. And while EF supports having an entity without a foreign key property, it's discouraged.
However in your case this is a Many-to-Many relationship. And in the relational model that uses a linking table, and the foreign key columns are on the linking table, not on the entity tables. The only thing on the entity is a Navigation Property, which is not structural, and can be omitted. You just need to tell EF the cardinality of the relationship, since in your current model the relationship is defined by convention based on the Navigation Properties.
So something like
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Configuration;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ef6test
{
public class Page
{
public int Id { get; set; }
public virtual ICollection<Container> Containers { get; set; }
}
public class Container
{
public int Id { get; set; }
// public virtual ICollection<Page> Pages { get; set; }
}
public class Db : DbContext
{
public DbSet<Page> Pages { get; set; }
public DbSet<Container> Containers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Page>()
.HasMany(p => p.Containers)
.WithMany();
}
}
class Program
{
static void Main(string[] args)
{
using (var db = new Db())
{
db.Database.Create();
}
}
}
}
David
This question is in regards to ASP.NET MVC 5.0 model class.
I have a ASP.NET MVC5.0 model class for example that looks like this
public class Car
{
public int ID { get; set; }
public string CarType { get; set; }
public string SelectedType { get; set; }
}
However, I do not want a database field created for this model for property SelectedType.
Is there any attribute available to tell the Entity Framework not to create a database field for SelectedType?
Thank you for your help in advance.
you can use Fluent API ignore for example;
modelBuilder.Entity<Department>().Ignore(t => t.Budget);
You can use the NotMapped Data Annotation to exclude a purticular property like below:
public class Car
{
//
[NotMapped]
public string SelectedType { set; get; }
}
You also can do this with Fluent API, but you need to override the OnModelCreating like below:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>().Ignore(n => n.SelectedType );
base.OnModelCreating(modelBuilder);
}
I am doing Entity Frameworks Database first approach, using EF 5.0, visual studio 2012 and Sql server management studio. Both Vs and ssms are express version.
I have several tables named ex. "User" or "Product", but when autogenerating the table mapping between an entity and a table, EF insists on mapping "User" to dbo.Users and "Product" to dbo.Products.
I have tried setting tools->options->databasedesigner->O/R designer->Pluralization of names to false.
When working with the *.edmx file in the EF designer in VS2012, I have also tried to set "Pluralize New Objects" to false.
In the EF Designer it correctly shows that "User" maps to the "User" table, but when I inspect my dbcontext object in debugging mode during runtime and finds the sql it uses to access the tables it access dbo.Users.
If I were using Code first approach this seems to be fixable by "modelBuilder.Conventions.Remove();" in the ModelBuilder, but how is this problem solved using the Database first approach?
I should probably say that I use a IDbcontext for testing purpose
using System.Data.Entity.Infrastructure;
namespace XX.Core
{
public interface IDbContext : IDisposable
{
IQueryable<T> Query<T>() where T : class;
void Add<T>(T entity) where T : class;
void Delete<T>(T entity) where T : class;
void Update<T>(T entity) where T : class;
Boolean Any<T>() where T : class;
int SaveChanges();
void Dispose();
}
}
and my actual dbcontext when not testing
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
namespace XX.Core.Model
{
public class XXDb : DbContext, IDbContext
{
public XXDb()
: base("name=XX")
{
}
public DbSet<User> Users { get; set; }
public DbSet<YY> Products { get; set; }
public DbSet<Offer> YY { get; set; }
public DbSet<ZZ> ZZ { get; set; }
IQueryable<T> IDbContext.Query<T>()
{
return Set<T>();
}
void IDbContext.Add<T>(T entity)
{
Set<T>().Add(entity);
}
void IDbContext.Delete<T>(T entity)
{
Set<T>().Remove(entity);
}
void IDbContext.Update<T>(T entity)
{
Set<T>().Attach(entity);
SaveChanges();
}
Boolean IDbContext.Any<T>()
{
return Set<T>().Any();
}
}
}
I have multiple models (tasks/servers/etc.) and all of these models need to support comments. I would like to have a centralized comments table that all of these models can reference (I am open to other designs though).
The comments table will have the following fields:
CommentID
RefTable
RefId
Text
I can use the following code in the task class (for example) to reference the task's comments.
IEnumerable<Comment> comments = Comment.Find(this.GetType().Name, this.TaskID)
However, I would prefer to create a HasMany mapping from tasks to comments so that I can use the following code.
this.Comments
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.ModelConfiguration;
namespace Models.Mapping
{
public class TaskMap : EntityTypeConfiguration<Task>
{
public TaskManagerItemMap()
{
// Primary Key
this.HasKey(t => t.TaskID);
...
this.Property(t => t.TaskID).HasColumnName("TaskID")
...
this.ToTable("Task");
}
}
}
using System;
using System.Collections.Generic;
namespace Models
{
public partial class Task
{
public int TaskID { get; set; }
....
public virtual IEnumerable<Comment> Comments { get; set; }
...
}
}
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.ModelConfiguration;
namespace Models.Mapping
{
public class CommentMap : EntityTypeConfiguration<Comment>
{
public CommentMap()
{
this.HasKey(t => new { t.RefID, t.RefTable });
this.ToTable("Comment");
this.Property(t => t.CommentID).HasColumnName("CommentID")
.IsRequired();
this.Property(t => t.RefID).HasColumnName("RefID")
.IsRequired();
this.Property(t => t.RefTable).HasColumnName("RefTable")
.IsRequired();
this.Property(t => t.Text).HasColumnName("Text")
.IsRequired();
}
}
}
using System;
using System.Collections.Generic;
namespace Models
{
public partial class Comment
{
public int CommentID { get; set; }
public int RefID { get; set; }
public string RefTable { get; set; }
public string Text { get; set; }
}
}
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Globalization;
using Vocus50.SiteManager.SiteManager2014.Models.Mapping;
namespace Models
{
public partial class DataContext : DbContext
{
static DataContext()
{
Database.SetInitializer<DataContext>(null);
}
public DataContext()
: base("Name=DataContext")
{
}
public DbSet<Task> Task{ get; set; }
public DbSet<Comment> Comment { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TaskMap());
modelBuilder.Configurations.Add(new CommentMap());
}
}
}
If you use the above code, it would seem to me the issue would be in sending over the RefTable (or RefModel from above - are those supposed to be the same?) One option here (there may be many others) would be to override SaveChanges and inspect the value (or fill in) upon save.
So if you override SaveChanges (a rough method below, there are many samples on the net) you would fill in this table based on the entity type. It feels hacky, so there is probably a better solution
Is there an easy way to make EntityFramework use SQL default values?
That is of course if I understood this correctly : )
Have you looked into using Automapper. I believe you can use this for the functionality your looking for.