In my project I use MVC4 and some external database using Entity as orm.
I decided to use membership given by MVC, so I just changed in default ConnectionString to point to my external db.
Then, when I launch the app first time, few tables were added, so far so good. Now, the problem is , that when I map new created userProfile table into my dataContext model, then I have a conflict, because this table allready exists in accountModel.
Account model and my new generated model are in the same namespace, which I don't wanna change, so what can I do?
here is class generate by ADO entity model using view add tables method:
public partial class UserProfile
{
public UserProfile()
{
this.Predictions = new HashSet<Prediction>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<Prediction> Predictions { get; set; }
}
and here from membership
[Table("UserProfile")]
public partial class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
both exist in the same name space, and are in conflict.
You can remove the auto generated class and create a partial class to extend the AccountModel UserProfile class instead.
Create a partial class with the same name and same namespace:
public partial class UserProfile
{
public UserProfile()
{
this.Predictions = new HashSet<Prediction>();
}
public virtual ICollection<Prediction> Predictions { get; set; }
}
By doing this, you have the Predictions property into the membership UserProfile class.
Related
I am developing an application in razor web apps (asp.netcore) and scaffolding db tables using efcore.
I performed a db-scaffold on my OnlineForms data table, which created my OnlineForms.cs Class. When i directly put the [key] attribute on top of the formid property in this class, I can save to the data table without any issues.
But when I move the [key] data annotation into the partial class OnlineFormsValidation, which references OnlineForms, through the [ModelMetadataType] attribute, and I try to save data; I get the error: "The entity type 'OnlineForm' requires a primary key to be defined."
The Required annotations work properly from inside OnlineFormsValidation class, but the [Key] annotation does not.
Thank you in advance. Any help would be greatly appreciated.
OnlineForm.cs:
namespace VehicleTakeHomeApp.Data.Models
{
public partial class OnlineForm {
[Key] <== works if i put it here, but I want to move it to OnlineFormValidation.cs
public int FormId { get; set; }
public string EmployeeId { get; set; }
public string Name { get; set; }
}
}
OnlineFormValidation.cs:
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
namespace VehicleTakeHomeApp.Data.Models
{
[ModelMetadataType(typeof(OnlineFormValidation))]
public partial class OnlineForm
{
}
public class OnlineFormValidation
{
[Key] <== this annotation is not getting picked up, even though the Required annotations below it get picked up.
public int FormId { get; set; }
[Required(ErrorMessage = "Employee ID is required.")]
public string EmployeeId { get; set; }
[Required(ErrorMessage = "Name is required.")]
public string Name { get; set; }
}
}
I had the OnModelCreating method in my dbcontext class commented out. This method contains the HasKey() from the initial db-scaffold.
I uncommented the OnModelCreating method, and now I don't need to add the [Key] annotation, to either class and it works.
It's more of a workaround then a solution, but its works.
I am trying to use partial classes to decorate EF's auto-generated entity models for SQL views that I have access to. These views are 1:1 representations of tables, but omit the primary keys and foreign key constraints present in the database. I would like to reproduce these keys/constraints with data annotations, but attempting to use them within EF fails.
Any attempts to use Include or Find within LINQ always fail. The foreign key defined here, for example, does not seem to be recognized:
public class FactTimeEntryMetadata
{
[Key]
public int TimeEntryKey { get; set; }
[ForeignKey("DimEmployee.EmployeeKey")]
public int EmployeeKey { get; set; }
}
[MetadataType(typeof(FactTimeEntryMetadata))]
public partial class FactTimeEntry { }
public class DimEmployeeMetadata
{
[Key]
public int EmployeeKey { get; set; }
}
[MetadataType(typeof(DimEmployeeMetadata))]
public partial class DimEmployee { }
In this example, the FactTimeEntry contains TimeEntryKey as a primary, and a column for EmployeeKey, referring to the foreign key in DimEmployee. Is my syntax off in some way, or is this simply not possible with Entity Framework database-first?
Edit:
I have also tried to add a virtual reference to the object, like so:
public class FactTimeEntryMetadata
{
[Key]
public int TimeEntryKey { get; set; }
[ForeignKey("DimEmployee")]
public int EmployeeKey { get; set; }
public virtual DimEmployee DimEmployee { get; set; }
}
[MetadataType(typeof(FactTimeEntryMetadata))]
public partial class FactTimeEntry { }
public class DimEmployeeMetadata
{
[Key]
public int EmployeeKey { get; set; }
}
[MetadataType(typeof(DimEmployeeMetadata))]
public partial class DimEmployee { }
but was also unsuccessful this way.
Your only three options using ef-database-first:
Put your keys and relationships in your database. Relational Databases were created to be relational. If you don't do that, why use a database?
As Gert Arnold metion in his comment, edit the EDMX and assign your associations.
Edit the T4 templates with custom code to add Keys/relationships to your objects.
I'm trying to go through this tutorial on the External Authentication Services (C#). I need some initial explanations to go forward. Looking inside the default template that ships MVC5, I see this:
// You can add profile data for the user ...
public class ApplicationUser : IdentityUser
{
public string HomeTown { get; set; }
public DateTime? BirthDate { get; set; }
}
What if I want to call it User instead of ApplicationUser? Maybe I want to add a navigation properties so I can establish relationship with my other models? Also when I look at the table, the name is AspNetUsers instead of ApplicationUser. Finally, What if I want to use my own context?
Thanks for helping.
1)What if I want to call it User instead of ApplicationUser?
You can change to any names you want, just make sure to replace ApplicationUser with the name.
2)Maybe I want to add a navigation properties so I can establish
relationship with my other models?
If you have a class call Address, you want to add addressId as a foreign key, see below:
public class Address
{
public int Id { get; set; }
public string Street { get; set; }
}
public class User : IdentityUser
{
public string HomeTown { get; set; }
public DateTime? BirthDate { get; set; }
public int AddressId { get; set; }
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<User>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
public DbSet<Address> Addresses { get; set; }
}
3)Also when I look at the table, the name is AspNetUsers instead of
ApplicationUser.
ASP.NET Identity is inherited from the The ASP.NET membership system. When you register a new user
using the default template, AspNetUsers and AspNetUserRoles etc.. these tables are created by default.
You can modify these table name by modifying the IdentityModel.cs. For more detail take a look at the following link:
How can I change the table names when using Visual Studio 2013 ASP.NET Identity?
4)What if I want to use my own context?
You can create your own DBContex, MVC 5 allow you to have mutiple DBContext, such as ApplicationDbContext and DataDbContext(custom DbContext).
ApplicationDbContext usually contains ASP.NET Membership data table.
DataDbContext usually contains data tables unrelated to users.
public class Blog
{
public int BlogId { get; set; }
public int Title { get; set; }
}
public class MyDbContext : DbContext
{
public MyDbContext()
: base("DefaultConnection")
{
}
public DbSet<Blog> Blogs { get; set; }
}
Note: You may need to use EF Migrations, see details here :
ASP.Net Identity customizing UserProfile
I'm trying to understand the best way to map the fields in an Edit Model (posted back from a view form) to a Domain Model so that I can SubmitChanges() and update the database record (via Linq to SQL). My example will be simple and the answer to it is probably to just do it manually. The question I'm asking is for models with many more fields where it could still be done manually and maybe that's the answer - but is there an easier way (using AutoMapper perhaps)?
My Domain Model:
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public int Color { get; set; }
public string SerialNumber { get; set; }
}
My View/Edit Model:
public class ProductVM
{
public int ProductId { get; set; }
public string Name { get; set; }
public IEnumberable<Color> Colors { get; set; } // To populate a dropdown in the view with color key/values
}
My Controller Action:
[HttpPost]
public ActionResult UpdateProduct(ProductVM product)
{
var productService = new ProductService();
productService.Update(product);
}
The Update method in my service layer:
public void Update(ProductVM productVM)
{
Product product = dataContext.Products.Single(p=>p.ProductId == productVM.ProductId);
// What's the best way to map the fields of productVM into product so I can submit the changes?
dataContext.SubmitChanges();
}
I just want to map the fields from productVM that match up with the fields in product. The Edit Model has fields that don't exist in the Domain Model and the Domain Model has fields that don't exist in the Edit Model. My ultimate goal is to update the fields in the database from the fields in the Edit Model.
Thanks
Use Automapper
public void Update(ProductVM productVM)
{
Product product = dataContext.Products.Single(p=>p.ProductId == productVM.ProductId);
AutoMapper.Mapper.DynamicMap<ProductVM, Product >(productVM, product );
dataContext.SubmitChanges();
}
here is my model classes;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ContactFormWithMultipleCheckboxApp.Models {
public class Product {
public int ProductId { get; set; }
[Required, StringLength(50)]
public string ProductName { get; set; }
public string Description { get; set; }
public virtual ICollection<Message> Messages { get; set; }
}
public class Message {
public int MessageId { get; set; }
public string From { get; set; }
[Required]
//below one is to validate whether the e-mail address is legit or not
[RegularExpression("\b[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2,4}\b")]
public string Email { get; set; }
[StringLength(100)]
public string Subject { get; set; }
public string Content { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
}
}
And I have installed MvcScaffolding as nuget package to my app. I am trying to a simple scaffolding with following code;
PM> Scaffold Controller Message
it works and creates my controllers, views and DBContect class. but I have one problem. why does it pluralize my dbset item inside dbcontect class;
public class ContactFormWithMultipleCheckboxAppContext : DbContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, add the following
// code to the Application_Start method in your Global.asax file.
// Note: this will destroy and re-create your database with every model change.
//
// System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<ContactFormWithMultipleCheckboxApp.Models.ContactFormWithMultipleCheckboxAppContext>());
public DbSet<ContactFormWithMultipleCheckboxApp.Models.Message> Messages { get; set; }
}
as you can see it creates the name as Messages but it uses Message on the other places like view and controller.
What is happening here?
In this blog post about MvcScaffolding 0.9.4, Steve Sanderson writes:
"Based on your feedback, controller
names are now pluralized by default
(e.g., you get PeopleController rather
than PersonController for a model of
type Person, unless you explicitly
enter PersonController as the
controller name when scaffolding)"
So by default (or convention) it pluralizes your names unless you tell it not to. You stated that you did that, and it didn't pluralize your controller or views.
I wonder if you also need to tell EntityFramework not to pluralize. See this post, "How to singularize in EntityFramework" for more details about that.