How to make changes in POCO file in Entity Framework so changes are retained - asp.net

I am using Database First approach in Entity Framework. I have a table which contain one field called CustomerName and it is NOT NULL.
The generated POCO is given below.
public partial class Customers
{
public string CustomerName {get; set;}
}
I have two questions.
How can I make this a required field so my code would become like this (shown below). As you know POCO is automatically generated so after I do this and update model from database, all my code is removed.
public partial class Customers
{
[Required]
public string CustomerName {get; set;}
}
Second question is why EF automatically doesn't apply [Required] with this field when generating code? The field is NOT NULL in database so shouldn't this be done automatically without having to manually write [Required]?

Here's the answer if you're using EF6:
Notice that the generated Customers class is partial, we're going to leverage that. First, we'll need to create a new Customers partial class with the exact same name within the exact same namespace:
namespace WebApp.TheSameNamespaceAsTheGeneratedCustomersClass
{
public partial class Customers
{
}
}
Now both of these partials make up the same class it's just that the source code of this class is now split in different files, one of which is generated by the tool and one that you wrote by hand. The difference of course is that you can change the latter without it getting rewritten all the time.
Note that the namespace has to match but the folder that contains the class file doesn't.
Now we need to create the metadata class that contains all the necessary attributes and decorate our Customers partial with it, like so:
namespace WebApp.TheSameNamespaceAsTheGeneratedCustomersClass
{
[MetadataType(typeof(CustomersMetadata))] //decorating the entity with the metadata
public partial class Customers
{
}
public class CustomersMetadata //metadata class
{
[Required] //your data annotations
public string CustomerName { get; set; } //the property name has to match
}
}
and that's it.
Is it verbose? Yeah, but that decision was made when db first was chosen.
A word of caution:
If you're doing this to use entity classes as data models in MVC, generally speaking, that's considered a bad practice. The recommended way is to create separate model classes and map data from and to entities. There are some security reasons for that, which you should research before you make the final decision.

If you are using ef core then try adding --data-annotations flag in your scaffold command.
Please refer for more info: https://learn.microsoft.com/en-us/ef/core/managing-schemas/scaffolding?tabs=dotnet-core-cli#fluent-api-or-data-annotations

EF doesn't have any means of validating your data in your POCO classes when it generates sql. That is why it is recommended that we should have a corresponding model object layer (corresponding model classes for your entities) that your application can manipulate. You can use something like AutoMapper for mapping between models and entities. In this way you can modify your model classes without impacting your EF entities.

Related

.NET Core 2.1 Identity : Creating a table for each Role + bridge M:M table

I'm having issues in figuring out the best design that fits my needs regarding a Role based authorizations using Identity in a .NET Core 2.1 project.
I already extended the User class from Identity with an ApplicationUser class.
I need 5 different roles to control the access to the different features of the app :
Admin, Teacher, Student, Parent and Supervisor
All the common attributes are kept in User and ApplicationUser but I still require different relationships to other tables depending of the User's Role.
User in Role Teacher is linked to 1-N School
User in Role Student is linked to 1-N GroupOfStudents (but not to a School directly)
User in Role Parent is linked to 1-N Student (but not to a School)
...
The other requirement is that a User must be able to be in 1-N Role.
What would be the best practice in my case?
Is there something I'm missing in the features of Identity?
My idea at first was to use nullable FK, but as the number of role increased, it doesn't look like a good idea to have so many empty fields for all those records.
I was thinking of using a "bridge table" to link a User to other tables for each role.
Have a many-to-many relationship between ApplicationUser and the bridge table nd a 0-1 relationship between the bridge table and individual tables for each role. But that's not really helping either since every record will produce the same amount of empty fields.
I'm fairly new with .NET Core and especially Identity, I'm probably missing some keywords to make an effective research because it looks to me that it's a really basic system (nothing really fancy in the requirements).
Thanks for reading !
EDIT :
I don't really have a error right now since I'm trying to figure out the best practice before going deeper in the project. Since it's the first time I face that kind of requirement, I'm trying to find documentation on what are the pros/cons.
I followed Marco's idea and used inheritance for my role based models as it was my first idea. I hope it will help understand my concern.
public class ApplicationUser : IdentityUser
{
public string CustomTag { get; set; }
public string CustomTagBis { get; set; }
}
public class Teacher : ApplicationUser
{
public string TeacherIdentificationNumber { get; set; }
public ICollection<Course> Courses { get; set; }
}
public class Student : ApplicationUser
{
public ICollection<StudentGroup> Groups { get; set; }
}
public class Parent : ApplicationUser
{
public ICollection<Student> Children { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public string Category { get; set; }
}
public class StudentGroup
{
public int Id { get; set; }
public string Name { get; set; }
}
This creates the database having one big table for the User containing all the attributes :
User table generated
I can use this and it will work.
A user can have any of those nullable fields filled if he requires to be in different role.
My concern is that for each record I will have a huge number of "inappropriate fields" that will remain empty.
Let's say that on 1000 users 80% of the users are Students.
What are the consequences of having 800 lines containing :
- an empty ParentId FK
- an empty TeacherIdentificationNumber
And this is just a small piece of the content of the models.
It doesn't "feel" right, am I wrong?
Isn't there a better way to design the entities so that the table User only contains the common attributes to all users (as it is supposed to?) and still be able to link each user to another table that will link the User to 1-N tables Teacher/Student/Parent/... table?
Diagram of the Table-Per-Hierarchy approach
EDIT 2:
Using the answer of Marco, I tried to use the Table-Per-Type approach.
When modifying my context to implement the Table-Per-Type approach, I encountered this error when I wanted to add a migration :
"The entity type 'IdentityUserLogin' requires a primary key to be defined."
I believe this happens because I removed :
base.OnModelCreating(builder);
Resulting in having this code :
protected override void OnModelCreating(ModelBuilder builder)
{
//base.OnModelCreating(builder);
builder.Entity<Student>().ToTable("Student");
builder.Entity<Parent>().ToTable("Parent");
builder.Entity<Teacher>().ToTable("Teacher");
}
I believe those identity keys are mapped in the base.OneModelCreating.
But Even if I Uncomment that line, I keep the same result in my database.
After some research, I found this article that helped me go through the process of creating Table-per-type models and apply a migration.
Using that approach, I have a schema that looks like this :
Table-Per-Type approach
Correct me if I'm wrong, but both Techniques fits my requirements and it is more about the preference of design? It doesn't have big consequence in the architecture nor the identity features?
For a third option, I was thinking to use a different approach but I'm not too sure about it.
Does a design like this could fit my requirements and is it valid?
By valid, I mean, it feels weird to link a teacher entity to a Role and not to a User. But in a way, the teacher entity represent the features that a User will need when in the teacher role.
Role to Entities
I'm not yet too sure of how to implement this with EF core and how overriding the IdentityRole class will affect the Identity features. I'm on it but haven't figured it out yet.
I suggest you take advantage of the new features of asp.net core and the new Identity framework. There is a lot of documentation about security.
You can use policy based security, but in your case resource-based security seems more appropriate.
The best approach is to not mix contexts. Keep a seperation of concerns: Identity context (using UserManager) and business context (school, your DbContext).
Because putting the ApplicationUser table in your 'business context' means that you are directly accessing the Identity context. This is not the way you should use Identity. Use the UserManager for IdentityUser related queries.
In order to make it work, instead of inheriting the ApplicationUser table, create a user table in your school context. It is not a copy but a new table. In fact the only thing in common is the UserId field.
Check my answer here for thoughts about a more detailed design.
Move fields like TeacherIdentificationNumber out of the ApplicationUser. You can either add this as claim to the user (AspNetUserClaims table):
new Claim("http://school1.myapp.com/TeacherIdentificationNumber", 123);
or store it in the school context.
Also instead of roles consider to use claims, where you can distinguish the claims by type name (e.g. http://school1.myapp.com/role):
new Claim("http://school1.myapp.com/role", "Teacher");
new Claim("http://school2.myapp.com/role", "Student");
Though I think in your case it may be better to store the information in the school context.
The bottom line, keep the Identity context as is and add tables to the school context instead. You don't have to create two databases, just don't add cross-context relations. The only thing that binds the two is the UserId. But you don't need an actual database relation for that.
Use UserManager, etc. for Identity queries and your school context for your application. When not for authentication you should not use the Identity context.
Now to the design, create one user table that has a matching UserId field to link the current user. Add fields like name, etc only when you want to show this (on report).
Add a table for Student, Teacher, etc. where you use a composite key: School.Id, User.Id. Or add a common Id and use a unique constraint on the combination of School.Id, User.Id.
When a user is present in the table this means that the user is a student at school x or teacher at school y. No need for roles in the Identity context.
With the navigation properties you can easily determine the 'role' and access the fields of that 'role'.
What you do is completely up to your requirements. What you currently have implemented is called Table-Per-Hierarchy. This is the default approach, that Entity Framework does, when discovering its model(s).
An alternative approach would be Table-Per-Type. In this case, Entity Framework would create 4 tables.
The User table
The Student table
The Teacher table
The Parent table
Since all those entities inherit from ApplicationUser the database would generate a FK relationship between them and their parent class.
To implemt this, you need to modify your DbContext:
public class FooContext : DbContext
{
public DbSet<ApplicationUser> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().ToTable("Students");
modelBuilder.Entity<Parent>().ToTable("Parents");
modelBuilder.Entity<Teacher>().ToTable("Teachers");
}
}
This should be the most normalized approach. There is however a third approach, where you'd end up with 3 tables and the parent ApplicationUser class would be mapped into its concrete implementations. However, I have never implemented this with Asp.Net Identity, so I don't know if it would or will work and if you'd run into some key conflicts.

Where should Stored Proc business logic be placed in MVC?

I'm looking for a bit of experience and explanation here, given that different sources give different recommendations. I am totally new to MVC. I know this question has been asked before, but I am not (currently) using EF or Linq.
I have a SQL database with many stored procedures. Previously when used with webforms, there was a business layer that contained helper methods for calling the procedures and returning DataSets to the pages. The important part is that the procedures often interrogated about 20 tables; the pages do not simply reflect the database structure exactly (as I see in the majority of MVC tutorials):
SQL database <--> stored procedures <--> business layer <--> web forms
I want to take the best approach here to start on the right footing and learn properly but appreciate there may not be a correct answer. Therefore if you post, could you please offer some explanation as to "why"?
Should stored procedure logic (SQLCommand/business methods etc) go within Model or
Controller?
One post advises neither, but retain the business layer. Another expert advises that
[Models/Entities] should not have any addon methods outside of what's
coming back from the database
If the business layer is retained, where are the methods called from (e.g. Model or Controller)?
If the above answer is "Neither", does that mean the Model part will go unused?
That almost feels that things aren't being done properly, however in this tutorial that appears to be what happens.
Should I plug in the Entity Framework into the Model layer to call the business layer?
That feels like overkill, adding all that additional logic.
Your controllers should gather the information required to build the page the user is currently viewing. That's it.
Controllers should reference classes in your business logic layer.
For example here's your controller. All it does is translate the http request and call the business logic.
public class MyController : Controller
{
private IMyBusinessLogic _businessLogic;
public MyController(IMyBusinessLogic businessLogic)
{
_businessLogic = businessLogic;
}
[HttpPost]
public ActionResult UpdateAllRecords()
{
_businessLogic.UpdateAllRecords();
return Json(new Success());
}
}
And your business logic class
public class MyBusinessLogic : IMyBusinessLogic
{
public void UpdateAllRecords()
{
// call SP here
using(SqlConnection conn = new...
}
}
There are a number of advantages to this:
Your business logic is completely separated from your UI, there's no database code in your presentation layer. This means your controller can focus on it's job and code doesn't get polluted.
You can test your controller and see what happens when your business logic succeeds, throws exceptions etc.
For extra bonus points you should look into creating a data access layer.
public void DataAccess : IDataAccess
{
public void RunStoredProcedure(string spName)
{
}
}
Now you can test that your BLL is calling and processing your SP results correctly!
Expanded following the comment questioning the models:
Ideally your model should have no logic in it at all. It should simply represent the data required to build the page. Your object which you're loading represents the entity in the system, the model represents the data which is displayed on the page. This is often substantially lighter and may contain extra information (such as their address) which aren't present on the main entity but are displayed on the page.
For example
public class Person
{
public int PersonID {get;set;}
public string Firstname {get;set;}
public string Lastname {get;set;}
public Address Address {get;set;}
}
The model only contains the information you want to display:
public class PersonSummaryModel
{
public int PersonID {get;set;}
public string FullName {get;set;}
}
You then pass your model to your view to display it (perhaps in a list of FullNames in this case). Lots of people us a mapper class to convert between these two, some do it in the controller.
For example
public class PersonMapper
{
public PersonSummaryModel Map(Person person)
{
return new PersonSummaryModel
{
PersonID = person.PersonID,
FullName = string.Concat(person.Firstname, " ", person.Lastname)
};
}
}
You can also use some automatic solutions such at AutoMapper to do this step for you.
Your controller should really only be involved with orchestrating view construction. Create a separate class library, called "Data Access Layer" or something less generic, and create a class that handles calling your stored procs, creating objects from the results, etc. There are many opinions on how this should be handled, but perhaps the most
View
|
Controller
|
Business Logic
|
Data Access Layer
|--- SQL (Stored procs)
-Tables
-Views
-etc.
|--- Alternate data sources
-Web services
-Text/XML files
-and son on.
if you feel like learning tiers and best way
MSDN have great article on this link
MSDN

Entity Framework - Including tables not mapped in data model?

I think this question is probably fairly simple, but I've been searching around and haven't been able to find what I'm looking for.
My team and I are adding a new module to our existing web application. We already have an existing data model which is hooked up to our sql db, and it's pretty huge... So for the new module I created a new EF data model directly from our database with the new tables for the new module. These new tables reference some of our existing tables via foreign keys, but when i add those tables, all of the foreign keys need to be mapped for that table, and their tables, and their tables... and it seems like a huge mess.
My question is, instead of adding the old tables to the data model, since I'm only referencing the ID's of our existing tables for Foreign key purposes can I just do a .Includes("old table") somewhere in the DataContext class or should I go back and add those tables to the model and remove all of their relationships? Or maybe some other method I'm not even aware of?
Sorry for the lack of code, this is more of a logic issue rather than a specific syntax issue.
Simple answer is no. You cannot include entity which is not part of your model (= is not mapped in your EDMX used by your current context).
More complex answer is: in some very special case you can but it requires big changes to your development process and the way how you work with EF and EDMX. Are you ready to maintain all EDMX files manually as XML? In such case EF offers a way to reference whole conceptual model in another one and use one way relations from the new model to the old model. It is a cheat because you will have multiple conceptual models (CSDL) but single mapping file (MSL), single storage description (SSDL) and single context using all of them. Check this article for an example.
I'm not aware that you can use Include to reference tables outside of the EF diagram. To start working with EF then you only need to include a portion of the database in - if your first project is working with a discrete functional area which it probably would be. This might get round the alarming mess when you import and entire legacy database. It scared me when I tried to do it.
In our similar situation - a big legacy system that used stored procedures, we only added the tables that we were directly working at that time. Later on you can always add in additional tables as and when you require them. Don't worry about foreign keys in the EF diagram that are referencing tables that aren't included. Entity Framework happily copes with this.
It does mean running two business layers though one for entity framework and one for the old style data access. Not a problem for us though. In fact from what I've read about legacy system programming it's probably the way to go - you have a business layer with your scruffy old stuff and a business layer with your sparkly new stuff. Keep moving from old to the new until one day the old business layer evaporates into nothing.
You have to use [Include()] over the member.
For example:
// This class allows you to attach custom attributes to properties
// of the Frame class.
//
// For example, the following marks the Xyz property as a
// required property and specifies the format for valid values:
// [Required]
// [RegularExpression("[A-Z][A-Za-z0-9]*")]
// [StringLength(32)]
// public string Xyz { get; set; }
internal sealed class FrameMetadata
{
// Metadata classes are not meant to be instantiated.
private FrameMetadata()
{
}
[Include()]
public EntityCollection<EventFrame> EventFrames { get; set; }
public Nullable<int> Height { get; set; }
public Guid ID { get; set; }
public Layout Layout { get; set; }
public Nullable<Guid> LayoutID { get; set; }
public Nullable<int> Left { get; set; }
public string Name { get; set; }
public Nullable<int> Top { get; set; }
public Nullable<int> Width { get; set; }
}
}
And the LINQ should have
.Includes("BaseTable.IncludedTable")
syntax.
And for the entities which are not part of your model you have to create some view classes.

Initiate Properties automatically using StructureMap

If i have N numbers of classes on each of them i am declaring for example property which contains some app setting values from config file.
public static IAppSettings AppSettings { get; set; }
I want to populate this property automatically when class is created.
I am thinking to achieve this goal using StructureMap.
I want to "say" somehow only in one place, that if class contain this property populate it.
May be some one came across this and have any ideas?
ASP.NET/ASP.NET MVC, ConsoleApp/WinForms
If i have N numbers of classes on each
of them i am declaring for example
property which contains some app
setting values from config file.
You should consider having those N classes derive from a base class which contains this property:
public abstract Base
{
public IAppSettings AppSettings { get; set; }
}
then if you want to have this property automatically populated by StructureMap you should no longer instantiate them manually but always ask the container for a value.
For example in a ASP.NET MVC application I would use constructor injection to pass the value of IAppSettings to all the controllers that need it.
It sounds like you want a variation of the SettingsScanner described in this post: http://lostechies.com/joshuaflanagan/2009/07/13/how-we-handle-application-configuration/
You can get the full code for the scanner and ISettingsProvider from The FubuMVC source code:
https://github.com/DarthFubuMVC/fubumvc/blob/2e7ea30391eac0053300ec0f6f63136503b16cca/src/FubuMVC.StructureMap/SettingsScanner.cs

Adding new methods to LINQ to SQL generated classes

I am new to LINQ. I just dragged all my database tables onto the designer in a LINQ to SQL dbml. All my relationships are correct and look nice in the designer. I am able to pull data using simple LINQ code. I want to add my own methods now but don't want to blow away my changes if (when) I need to regenerate my dbml. I am guessing I just create a new class file and setup partial classes of the generated classes. Is this correct? For example, I have a generated class called SystemUser which contains the columns SystemUserId, Username, Password, PersonId, SecurityQuestionId, SecurityQuestionResponse. I want to add a method called void Authenticate() and a new property called bool Authenticated. Basically I want to pass in a username and password to Authenticate() and set the Authenticated property based on finding a matching user, etc. Where and how would I do this?
The LINQ-generated classes are partial classes, meaning you can extend them by creating your own partial classes or partial methods.
In your case, you can create a partial class for your SystemUser, and then add your method(s) in there. They will not be overwritten if the DBML file is regenerated.
Something like:
public partial class SystemUser
{
public bool Authenticated { get; set; }
void Authenticate()
{
//Perform custom logic here.
}
}
Take a look at using a Partial class... it might fit your situation very nicely.
If you just want your class to have a new method you are correct create a new file and use partial class.

Resources