Wanted to get some clarity on something in regards to how we are implementing our Metadata.
Our Breeze Api is not directly tied to SQL Server so we have implemented a custom EFContextProvider and the DbSet below....
public class MetadataDbContext : DbContext
{
public MetadataDbContext()
: base(nameOrConnectionString: "MetadataDb")
{
Database.SetInitializer<MetadataDbContext>(null);
}
public DbSet<Order> Orders { get; set; }
public DbSet<OrderMeter> OrderMeters { get; set; }
public DbSet<OrderDemand> OrderDemand { get; set; }
public DbSet<MeterHistory> MeterHistory { get; set; }
public DbSet<FieldTech> FieldTechs { get; set; }
public DbSet<Dispatcher> Dispatchers { get; set; }
public DbSet<OrderLookupData> LookupData { get; set; }
public DbSet<Organization> Organizations { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<Alert> Alert { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
As you can see I am pointing that DbSet at a database called "MetadataDb" which is just an sdf file we deploy with our project. We then override SaveChangesCore in the Context Provider to route our saves to the correct services instead of going direct to Entity Framework. My question is during some testing we noticed that it seemed Breeze was trying to update the sdf file in some cases. It did not appear that the size of the file changed, but just wanted to make sure before we go to production that the sdf file we are pointing the Metadata at does not grow on our server.
Thanks really enjoy using Breeze.
If the only thing that you are using the .sdf file for is to return metadata then Breeze doesn't do anything more than extract the "edmx" from the ObjectContext or DbContext associated with your database. My guess is that just the act of spinning up the context is causing EF to "modify" the "sdf" file. Breeze is not doing anything to touch the database directly.
Related
My current aim is to build a database structure using classes in Entity Framework & ASP MVC.
I currently have a Users table and a Posts table. What I would like to do is create a many to many relationship for Users who have liked Posts (whilst conserving who created the post). And be able to access for each user all of the posts they have liked. Currently I have these classes but I'm unsure of how to link them as all of the online examples are linking Primary Keys from different databases where I just want to use the Username Parameter. Any help would be great. I have this so far.
public class Posts
{
[Key]
public virtual int PostId { get; set; }
public virtual string Title { get; set; }
public virtual string URL { get; set; }
[DisplayName("Main Text")]
public virtual string TextBody { get; set; }
public int PostLikes { get; set; }
private DateTime Datedata = DateTime.Now;
public DateTime PostDate { get { return Datedata; } set { Datedata = value; } }
public virtual Users User { get; set; }
public ICollection<PostLikes> UsersWhoHaveSigned { get; set; }
}
{
public class Users
{
[Key]
public virtual int UserId { get; set; }
public virtual string Username { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual List<Posts> Post { get; set; }
}
}
I have not built the UsersWhoHaveSigned table yet. Early experimentation caused me so much backtracing it was painful. Any help would be great.
Edit: I was hoping to ask for help and then appropriate that informtaion to fit my example which utilises the individual accounts add-on. This produces some addition files that are now causing interference with the code you've provided.
Here is the IdentityModels.cs file.
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
namespace Coursework2.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit https://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
}
I believe that the assembly directives at the top are preventing system.data.entity from being used so when I try to implement ApplicationDbContext : DbContext I get error messages :/
Ideally I'm looking to use the IdentityModels.cs file as a replacement for the users class. But still very lost.
First of all, I recommend that you use the singular form for your class names, as EF will automatically pluralize table names.
Second, for a key property, you can just use the term Id, without any annotations, and EF will pick it up as the principal key.
Finally, I'll assume you are looking to use a Code-First approach. Consider the following classes (yours, but refactored for clarity purpose):
public class Post
{
public virtual Guid Id { get; set; }
public virtual string UserName { get; set; }
public virtual User User { get; set; }
public virtual ICollection<PostLike> Likes { get; set; }
}
public class PostLike
{
public virtual Guid Id { get; set; }
public virtual Guid PostId { get; set; }
public virtual Post Post { get; set; }
public virtual string UserName { get; set; }
public virtual User User { get; set; }
}
public class User
{
public virtual Guid Id { get; set; }
public virtual string UserName { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public virtual ICollection<PostLike> Likes { get; set; }
}
To make it work, you'd need a DbContext such as the following. Pay attention to the OnModelCreating method, which is where the magic happens:
public class ApplicationDbContext
: DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Post> Posts { get; set; }
public DbSet<PostLike> PostLikes { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasAlternateKey(u => u.UserName);
modelBuilder.Entity<User>()
.HasMany(u => u.Posts)
.WithOne(p => p.User);
modelBuilder.Entity<Post>()
.HasOne(p => p.User)
.WithMany(u => u.Posts)
.HasForeignKey(p => p.UserName)
.HasPrincipalKey(u => u.UserName);
modelBuilder.Entity<Post>()
.HasMany(p => p.Likes)
.WithOne(pl => pl.Post);
modelBuilder.Entity<PostLike>()
.HasOne(pl => pl.Post)
.WithMany(p => p.Likes);
modelBuilder.Entity<PostLike>()
.HasOne(pl => pl.User)
.WithMany(u => u.Likes)
.HasForeignKey(pl => pl.UserName)
.HasPrincipalKey(u => u.UserName);
}
}
Voila! I hope it answers your question ;)
If so, please don't forget to mark my post as the answer!
Edit:
I'll provide some explanations, that I had left out to answer your question ASAP.
So, first thing you need to do, is to declare the UserName as an alternate key, because you want to create relationships depending on it, and you already have the 'Id' principal key declared.
Second, on each object that should own a User reference base on the UserName alternate key, you need to declare the object's UserName property as the foreign key of the relationship, and the User's UserName property as the principal key.
In other words, the foreign key is the property that a referencing object uses for the relationship, and the principal key is the property based on which the referenced object is bound to the referencing one.
Note that principal keys must have a key or alternate key constraint, or it won't work.
Just to comment on your answer. I found that I had to use
using Microsoft.EntityFrameworkCore and remove System.Data.Entity - This was causing the program to be confused as to which DbContext I wanted to use. Thanks!
I am working in my MVC5 project and I have created a DbContext different to the ApplicationDbContext but it inherits from the same class. I have been developing some parts of my project but now I want to add all the authentication and authorization stuff. But the tables that ASP.NET creates automatically for this purpose don't show up in my Server Explorer although I can work with the sets named Users and Roles of my context. I have searched the reasons of this but I found nothing useful. I hope someone can answer my question and whether it is an important issue or not. I add the code of my DbContext class. Sorry for my English cause I know it is terrible.
namespace GestionPaladares.Models
{
using System;
using System.Data.Entity;
using System.Linq;
using System.Data.Entity.ModelConfiguration.Conventions;
using GestionPaladares.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
public class PaladarContext : IdentityDbContext<ApplicationUser>
{
// Your context has been configured to use a 'CodeFirstDatabaseModel' connection string from your application's
// configuration file (App.config or Web.config). By default, this connection string targets the
// 'GestionPaladares.Models.CodeFirstDatabaseModel' database on your LocalDb instance.
//
// If you wish to target a different database and/or database provider, modify the 'CodeFirstDatabaseModel'
// connection string in the application configuration file.
public PaladarContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
// Add a DbSet for each entity type that you want to include in your model. For more information
// on configuring and using a Code First model, see http://go.microsoft.com/fwlink/?LinkId=390109.
public virtual DbSet<Product> Products { get; set; }
public virtual DbSet<FoodAndDrink> Foods { get; set; }
public virtual DbSet<SoldBill> SoldBills { get; set; }
public virtual DbSet<CostBill> CostBills { get; set; }
public virtual DbSet<Seller> Sellers { get; set; }
public virtual DbSet<Grocer> Grocers { get; set; }
public virtual DbSet<Owner> Owners { get; set; }
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Measure> Measures { get; set; }
public virtual DbSet<Edge> Edges { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
Add ApplicationUser in Dbcontext
public DbSet<ApplicationUser> ApplicationUser { get; set; }
For example,
namespace GestionPaladares.Models
{
using System;
using System.Data.Entity;
using System.Linq;
using System.Data.Entity.ModelConfiguration.Conventions;
using GestionPaladares.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
public class PaladarContext : IdentityDbContext<ApplicationUser>
{
// Your context has been configured to use a 'CodeFirstDatabaseModel' connection string from your application's
// configuration file (App.config or Web.config). By default, this connection string targets the
// 'GestionPaladares.Models.CodeFirstDatabaseModel' database on your LocalDb instance.
//
// If you wish to target a different database and/or database provider, modify the 'CodeFirstDatabaseModel'
// connection string in the application configuration file.
public PaladarContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
// Add a DbSet for each entity type that you want to include in your model. For more information
// on configuring and using a Code First model, see http://go.microsoft.com/fwlink/?LinkId=390109.
public virtual DbSet<Product> Products { get; set; }
public virtual DbSet<FoodAndDrink> Foods { get; set; }
public virtual DbSet<SoldBill> SoldBills { get; set; }
public virtual DbSet<CostBill> CostBills { get; set; }
public virtual DbSet<Seller> Sellers { get; set; }
public virtual DbSet<Grocer> Grocers { get; set; }
public virtual DbSet<Owner> Owners { get; set; }
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Measure> Measures { get; set; }
public virtual DbSet<Edge> Edges { get; set; }
public DbSet<ApplicationUser> ApplicationUser { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
Since you are using EF, you should first add migration, then do update database from the PM console window. Take a note you have to select the correct project form the list and be sure of the right connection string in your code or appsettings file.
Or, you have to create your own method to call on startup for fixing the database for you.
public static void EnsureDatabaseCreated(IConfiguration configuration)
{
using (var context = new DatabaseContext(configuration.GetConnectionString(GlobalConstants.APP_SETTINGS_CONNECTION_NAME)))
{
context.Database.Migrate();
}
}
public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
EnsureDatabaseCreated(this.configuration);
}
Change the DatabaseContext class name with yours.
Hope this helps.
I have just started looking into asp mvc core. According to MS poco databases remain the same.
Now all the code below has been working flawlessly on asp mvc 4 and also everything is saved in the database; As verified by sqlserverexplorer on visual studio 2015 update 3.
I can retrieve the data but after a while or after i restart the application and try to retrieve the property it says null, although I can view the data in the database.
Things tried
reinstalled vs
reinstalled mvc core
Viewed the examples on the official documentation/tutorial site
They use ICollection instead of List but they also says that you can use either.
builder.Entity().HasMany(u => u.storymode).WithOne(c => c.user);****
in the databse context OnModelCreating method.
***This line was making it keep the relationships until the application was restarted, hence it only saved the relations which were saved after the application started and lost after it restarted.
The current behavior is that it saves the data but it is not being retrieved.
Extra points
I am saving the data via a function defined below, that function belongs to a class which is injected as per the asp.net mvc core guidelines in the ConfigureServices method in the startup class.
My poco class is
public class modelsall
{
public virtual int modelsallId { get; set; }
[Required]
public virtual string username { get; set; }
[Required]
[DisplayName("Email")]
[DataType(DataType.EmailAddress)]
public virtual string email { get; set; }
[DataType(DataType.Text)]
public virtual string title { get; set; }
[DataType(DataType.Text)]
public virtual string extra { get; set; }
[Required]
[DataType(DataType.DateTime)]
public virtual DateTime startdate { get; set; }
public virtual string imageblob { get; set; }
public virtual List<comments> comments { get; set; }
public virtual List<storyfacequotes> faceq { get; set; }
//Tried adding this in desperation
//[ForeignKey("storypages")]
//public virtual int storyId { get; set; }
public virtual List<story> pages { get; set; }
//Tried adding this after a blogpost said it might help
public virtual ApplicationUser user { get; set; }
public virtual whatisit typ { get; set; }
}
Method for creating and saving
public async Task<bool> AddMainStory(string email, modelsall modelsall)
{
ApplicationUser user = await GetUser(email);
if (user == null)
{
return false;
}
modelsall.email = user.Email;
modelsall.user = user;
_context.models.Add(modelsall);
await _context.SaveChangesAsync();
if (user.mode == null)
{
user.mode = new List<modelsall>();
}
user.mode.Add(modelsall);
await _context.SaveChangesAsync();
return true;
}
property defined in ApplicationUser
public class ApplicationUser : IdentityUser
{
public virtual List<modelsall> mode { get; set; }
}
PS: I could not find a tag for asp.net mvc core, although, mvc5 is considered mvc core according to MS.
After a lot of research and not looking into the docs properly the first time,
you need this for making relationships
builder.Entity().HasMany(u => u.storymode).WithOne(c => c.user);
**** in the databse context OnModelCreating method.
but the entire thing resets if the application restarts so not an ideal solution.
For now you can either search each time, not much effect for small applications or use asp 5 and ef6.
Here is a list of features not included in ef core as of now.
I am using Visual Studio Express 2013 for Web (specifically version 12.0.21005.1 REL). This is my first project using VS2013, I've been using VS2012 up until this point.
I am attempting to create a new controller in my asp.net MVC application. I am using Entity Framework 5 with code first (.NET 4.5). I want Visual Studio to create the template for me (you know, a controller with views to read/write/delete etc, rather than write the code myself from scratch).
However, every time I try to create the controller I get the following error message:
Is there some sort of bug in VS 2013? I can't figure out what this means, and restarting VS2013 does not help.
Here are the gory details.... actually it is all very simple since this is a new project with very little code written so far.
My model:
namespace ProfessionalSite.Models
{
public class EntityModels
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
public class Enrollment
{
public int ID { get; set; }
public string EnrollmentName { get; set; }
public string Credits { get; set; }
}
// Create the class that inherits from DbContext
// The name of this class is also used as the connection string in web.config
public class EFDbContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
}
}
}
And in my web.config file I have the following
<add name="EFDbContext"
connectionString="Data Source=JONSNA\SQLEXP2012WT;Initial Catalog=ProfessionalSiteDb; Integrated Security=True; MultipleActiveResultSets=True"
providerName="System.Data.SqlClient"/>
within the tags.
Now time to create a controller. I right click on Controllers in the Solution Explorer, and choose to Add a new Controller.
And then
And when I click Add I get
I cant figure out how to get rid of this error. I guess as a workaround I can just type the code myself, but I'd like to know if this is a bug or something I have done wrong. In VS2012 this just worked...
I'd appreciate any help or pointers. Thanks.
You don't need the EntityModels class, See below:
namespace ProfessionalSite.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
public class Enrollment
{
public int ID { get; set; }
public string EnrollmentName { get; set; }
public string Credits { get; set; }
}
// Create the class that inherits from DbContext
// The name of this class is also used as the connection string in web.config
public class EFDbContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
}
}
Then when you create a controller, just select the Student or Enrollment for the Model class.
I was thinking that the purpose of EF DataMigrations is to preserve old data while changing the database structure. Do I think right? But when I update the database with migrations all the old data is erased.
Do I make something wrong or maybe it isn't possible to use data migrations in this kind of scenario ?
this is DbContext:
public class CodeFirstContext : DbContext
{
public CodeFirstContext() : base ("ZenRandevuIzle")
{
}
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Takvim> Takvims { get; set; }
public DbSet<Musteri> Musteris { get; set; }
public DbSet<Randevu> Randevus { get; set; }
public DbSet<SeansTuru> SeansTurus { get; set; }
public DbSet<Hizmet> Hizmets { get; set; }
public DbSet<Islem> Islems { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}
}
this is Global.asax:
Database.SetInitializer<CodeFirstContext>(new CodeFirstContextInit());
this is migration Config:
internal sealed class Configuration : DbMigrationsConfiguration<CodeFirstContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
Does the CodeFirstContextInit initialiser drop the database and recreate it (what is its base class?) normally I wouldn't have an initializer when using migrations.
To use EF 4.3 Code First Data Migrations with an existing database you need to create an "empty" migration so that the Migration-History table is created and a baseline can be established.
The Steps outlined in this post should help http://thedatafarm.com/data-access/using-ef-4-3-code-first-migrations-with-an-existing-database