I am developing a data intensive app in C# and need some advice on the best method to manage my data. My application will use a number of related tables with a lot of movement backwards and forwards between the app and the database.
My question is, what method would be best to handle data? All of my data fields are controlled within their own classes and collections, so hence, the question is really more of a case of what is the best method to bind my collections and objects to the database.
Should I manually create my own SQL connections / SQL Insert / Update queries, or is there another way to do this? For instance is it possible in Visual Studio to easily create a strongly typed data layer that will automatically look after Inserts / Updates / Deletes etc?
Many thanks
Q. For instance is it possible in Visual Studio to easily create a strongly typed data layer that will automatically look after Inserts / Updates / Deletes etc?
Entity Framework sounds like something you're looking for. There is, of course, some setup involved. With most web projects, Entity Framework is automatically added, and if not you can always add it via NuGet package manager.
EntityFramework binds your models to a Database through the DbContext object, and Code First will even generate a database if one does not exist based on your models (if one does exist and the models change, you might have to migrate: More reading). I will be taking that approach (you can later change the following code to a connection string to a live DB).
First, you need to tell your application what database to use (whether it exists or not), and this can be done in the Web.Config file (not the only approach).
Web.Config
<configuration>
....
<connectionStrings>
<add name="ConnectionStringName" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\DATABASENAME.mdf;Initial Catalog=DATABASENAME;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
NOTE - this connection string will only work in VS2015. For previous versions, use:
Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\DATABASENAME.mdf
More reading on configuring Entity Framework
Now, we can use "ConnectionStringName" to connect our context.
The Context class will have to inherit from the DbContext object, and we will pass this connection string name to the base constructor (DbContext exists in the System.Data.Entity namespace). I will use two generic models that look identical (ModelA ModelB) --
ModelA and ModelB
using System.ComponentModels.DataAnnotations;
public class ModelA
{
public int Id { get; set; }
[Required(ErrorMessage="You need to enter a name!")]
[StringLength(40)]
public string Name { get; set; }
}
NOTE - I'm using DataAnnotations (Required, StringLength) - these are really cool and can be very useful when implementing CRUD operations on your model.
ALSO -- Entity Framework will automatically make properties that are named: Id (or any case form) or ModelNameId the primary key. There are ways to override this.
More reading on DataAnnotations
You can even create your models with relationships in mind. If ModelA will have a one-to-many relationship with ModelB, you can reflect this relationship in code:
public virtual ICollection<ModelB> ModelBs {get; set;}
More reading on creating relationships
We will now map your models to tables using the DbSet collection. Here's how that looks:
using System.Data.Entity;
using YourProject.Data.Models;
namespace YourProject.Data.DAL
{
public class YourContext : DbContext
{
public YourContext() : base("ConnectionStringName")
{
}
public DbSet<ModelA> ModelAs { get; set; }
public DbSet<ModelB> ModelBs { get; set; }
}
}
Database Initialization Strategies - for seeding your database with data on creation.
More reading on configuring the context
I will never be able to detail everything you can do - but here are a few short examples:
Q. What does all this do?
You now have a strongly-typed object connected to your database. It's as simple as creating a new Context object:
YourContext yourContext = new YourContext();
Retrieving a whole table is as easy as:
IEnumerable<ModelA> modelAs = yourContext.ModelAs;
or finding a row by Id
ModelB modelB = yourContext.ModelBs.Find(id);
Say you grabbed modelB and want to update it. It's as easy as:
modelB.Name = "Here's the new name";
yourContext.Entry(modelB).State = EntityState.Modified;
yourContext.SaveChanges();
Adding:
yourContext.ModelAs.Add(newModel);
Removing:
yourContext.ModelBs.Remove(modelB);
REMEMBER Add/Update/Delete methods will ALL require a call to SaveChanges(); from the Context. Otherwise they will be discarded.
Of course, this is probably the most basic rundown of Entity Framework available. To see more of it in action check out these tutorials:
WebForms with Entity Framework - Wingtip Toys
MVC with Entity Framework - Contoso University
Hope this may be of assistance for someone.
Related
I have a specific EF Core 6.x question.
If the SQL table has a column removed. Then EF Core will throw a SqlException saying that it's an invalid column name unless I also update the C# model.
For example,
Create Table User
(
FirstName varchar(200)
,MiddleName varchar(200) null -- tried to remove this column after table is created
,LastName varchar(200)
)
I tried deleting the MiddleName column from the SQL Table. When I run a simple read call using EF Core 6, I get the error.
c# model
public class User
{
public virtual string FirstName { get; set; }
public virtual string? MiddleName { get; set; }
public virtual string LastName { get; set; }
}
var db = new EFDbContext(connectionString);
var data = db.Users.ToList(); // SqlException here after column removal
Is there any way to remove columns from the table without needing to update the c# class as well?
Tried making the C# property MiddleName not virtual.
Update:
In the event that I have an existing application. I would need to modify the c# model even if the codebase doesn't refer to the removed column anywhere. Alternatively, I can decorate the property with [NotMapped] or use the Ignore() method in the modelbuilder.
Both approaches means a rebuild of the assembly is needed and downtime during deployment.
NHibernate's mapping can be done using an XML file and thus all it takes would be a simple config file update.
I can't seem to find anything in EF Core that will reduce the headache of maintaining older codebases when schema changes occur.
EF creates a data model mapping internally to track the database schema and your code models. By removing the column in your database table, your code model no longer matches the database. Hence, the exception occurs.
This is definitely not be the answer you're looking for, but as far as I know EF Core need consistency between the models and the DB schemas to work.
I can think of 2 things here:
Maybe you could benefit from using a different ORM (Did you give Dapper a cahnce)
You might be facing an architectural issue, if there's more than one team working with the same database, and more than one system calling that database, the best way to avoid headaches in the future would be to isolate the data access layer and expose an API that serves all the involved systems.
That way, if the database changes, you just need to re-build the data access layer, no downtime for your clients.
And finally... in my opinion the ideal solution is a combination of both, create a decoupled data access layer, map things there and expose an API with the models your application needs.
I saw a lot of examples online but none that I could use from top to bottom about merging my own DbContext with Asp.net IdentityDbContext.
Can someone please walk me through it? I am at step 0, and what I want is to have the tables generated by ASP.net IdentityDbContext inside my own database, so that I can retain user data in my own database. How can I achieve that?
Thanx in advance :)
If I got you correct, you are trying to use your existing database, tables and existing users with asp.net identity framework.
First thing, according to my understanding, you can't merge your db context (MyDbContext) with 'IdentityDbContext', because context of asp.net identity framework tables has to be inherited from IdentityDbContext<YourUserTable>. But your other tables may inherited from DbContext.
Therefore you have to use two separate db contexts if you want to use identity framework build in method support, which is UserManager etc.
You can use your existing database with identity framework, you just need to correctly bind your database tables with identity framework EF code first approach using model binding.
There is a YouTube video tutorial which may help you to get some idea in order to achieve your task. Actually this video illustrates to use Identity 2.0 with existing database.
Part 1: https://www.youtube.com/watch?v=elfqejow5hM
Part 2: https://www.youtube.com/watch?v=JbSqi3Amatw
Hope this helps.
I'm not really sure what you're trying to achieve but check this question to see if it's of any help.
ASP.NET Identity DbContext confusion
Here's part of a walk-through I created. There are a few steps included specific to making it work with code first migrations but you should be able to accomplish what you want using these steps.
Start by creating a new ASP.NET MVC project. Call it Contacts if you want the included code to match. The authentication defaults to Individual User Accounts which is what we want in this case. Deselect Host in the Cloud for now. You can enter your publishing settings later. Once the project is created bring up the Package Manager Console and Install-Package EntityFramework. Now since we are doing Code First add a simple model class.
public class Contact {
public int ContactID { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
At this point you would usually add controllers and such but since this post is focusing on the data side of things we'll skip over all of that. Next we want to add our database context. Go ahead and add it right in the Models namespace.
public class ContactContext : IdentityDbContext {
public ContactContext()
: base("ContactContext") {
}
public DbSet<Contact> Contacts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public static ContactContext Create() {
return new ContactContext();
}
}
A couple of things to note here. Since we're consolidating the Identity tables into our application's context we want to inherit from IdentityDbContext instead of just DbContext. Also, I prefer not to use the generated "DefaultConnection" that gets created in Web.config so I'm passing "ContactContext" as the connection string name to the base constructor. We'll modify the connection string in a minute. If you're typing in the OnModelCreating method Visual Studio should add the call to base.OnModelCreating but if not make sure you add it since it's essential for building the identity tables. Although not essential, you can configure the modelBuilder not to pluralize table names. Add a Create method which is needed for the Identity code to use this context. Also, as you add code you'll need to right-click and Resolve to add the appropriate using statements.
As promised, here is the modified connection string to be updated in the web.config in the root of the site. The name property is changed to something that makes sense for the application and the AttachDbFilename and Initial Catalog values are changed to something a little more user friendly than the auto generated name.
<add name="ContactContext" connectionString="Data Source=
(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\ContactContext.mdf;Initial
Catalog=ContactContext;Integrated Security=True"
providerName="System.Data.SqlClient" />
Now go to the Models folder and open the IdentityModels.cs file. Cut the ApplicationUser class from here and paste it into your Contact.cs file. Again you'll have to resolve a few missing namespaces. At this point you can safely delete the IdentityModels.cs file. Since we've eliminated the ApplicationDbContext we'll need to do a find on ApplicationDbContext and replace it with ContactContext in a few places. You should be able to do a clean build.
What is the difference between a "model" and a "context" in Entity Framework jargon?
I'm using the Entity Framework database first approach in an application. These terms have come up many times as I've been reading different forums and articles on EF implementation strategies. I can't seem to figure out how these two are different (not even with just entity framework, but with software development in general). People use the words as if they are different, but then some people seem to use the words interchangeably.
Context
This is easy. The context is either the DbContext or the older ObjectContext class that is the core of the entity framework data access layer. It supplies transparent database access through strong typed sets of entities, tracks and saves changes, manages database transactions and connections, and contains a number of utility methods to facilitate all kinds of data access tasks (esp. DbContext).
Model
This can be two (or three) things.
The data model, or store model. Which is the relational model of the database underlying the EF data access layer.
The conceptual model, or class model. Which is the .Net class model that represents the database. This model can either be generated by EF (database-first) or it can be an existing class model (code first). The conceptual model and the store model are linked through mapping, so EF knows how to populate .Net classes from database records and, conversely, how to save .Net classes to the database.
Some people refer to the classes in the conceptual model as "models". This is not wrong, but I prefer to use the name entities for this.
So context and model are two quite different things. You might say that the context is the middleman between two different types of models.
Loosely speaking a context relates to a database connection or session wherea the model is the mapping between tables, views, etc to data access object classes (i.e., objects that will contain the data)
A model is a class which usually represents a database table or structure to display a database table. For example, if I had a database for cars, then a model for car could be
public class Car
{
[Key]
public int CarId { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
}
This model is used by entity framework and the sql provider (for mysql or mssql usually) to compose a query against a database. The query requires a way for this to be mapped, and that is the job of the context. The context usually extends DbContext and is what is used for the facade of accessing the database table as an in memory object.
public class CarContext : DbContext
{
DbSet<Car> Cars { get; set; }
}
i have some questions of how to use the Entity Framework in an enterprise application.
First of all, i work with ADO.NET for many years now and i use objects to reflect the data that i get from the database provider.
Every time i want to change something or insert something into the database.
I just call a Save() method and get the job done.
Every object has a DatabaseManager that manage the queries to the DataAccess layer.
For example
public class Article{
public int ID{get;set;}
public string Title{get;set;}
.....
public bool Save(){
if(this.ID == -1){
return new ArticleDatabaseManager().InsertArticle(this);
}else{
return new ArticleDatabaseManager().UpdateArticle(this);
}
}
}
public ArticleDatabaseManager : DatabaseManager
{
...ADO.NET code
}
I don't know if i have to use the same architectur or change all the way i use this objects in my application.
I thought if i create something like the above i can do something like this :
public class Article{
public int ID{get;set;}
public string Title{get;set;}
.....
public bool Save(){
if(this.ID == -1){
return new ArticleDatabaseManager().InsertArticle(this);
}else{
return new ArticleDatabaseManager().UpdateArticle(this);
}
}
}
In the Each DatabaseManager implements some Link To Entities or even EntitySQL to do the same job like the old DatabaseManager does.
Fill the Business models with the values that i from the Entity Objects.
Then i could work with the Business as before and just any time i want to do some changes i communicate via EntityFramework to the Database.
Sould i implement something like the above?
Sould i just inherit the previous business objects to the entity objects?
EX :
public class Article : ArticleEntity
{
//some properties for validation etc
}
Sould i use something completely different?
I Just Don't knwo:/
I have no experience with other ORM. Just mine hand written "ORM" System.
Thank you very much.
I'm sorry for my lack of English and i know that i ask too much in a single question...
But moving from one technology to an other for a dinosaur like me is like i change Country:/
Did you at least try to use some EF tutorial? If not it is time to do that because we cannot explain you everything about EF in single answer (even in multiple - that is not purpose of SO to replace tutorials and learning materials). That should give you pretty clear answer about all your stuff related to your database managers.
In general what you did till know is very close to Active record pattern. If your objects also has static methods used to retrieve object from database it is Active record pattern. When using EF you usually don't use this pattern and you don't need any database manager. EF is build around class which is called context and this context works as your database manager for all entities you are using. It is possible to add saving and retrieval methods to entities but because it breaks separation of concerns and it makes your entities heavily dependent on EF and persistence (trend is to make them completely independent = POCO) it is usually not used.
Don't derive any custom class from entity. EF will not be able to use your derived type. Use entity mapped in EF as your class and add all custom properties and methods directly to this class (you can even create that class from scratch if you don't want to use code generators). In case of generated entities you can add custom code in partial classes. If you don't use EF entity as your object you will have to manually handle conversion from one to other (or use some tool like AutoMapper).
EF is not able to work with XML column - it will handle it as string. Especially if you plan to use these data for some ordering or filtering and if they have fixed structure you should model them as separate tables / entities. If it is really just structured content (with dynamic structure) you can use it as XML string.
Okay, so i've studied c# and asp.net long enough and would like to know how all these custom classes i created relate to the database. for example.
i have a class call Employee
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
}
and i have a database with the following 4 fields:
ID
Name
EmailAddress
PhoneNumber
it seems like the custom class is my database. and in asp.net i can simple run the LINQ to SQL command on my database and get the whole schema of my class without typing out a custom class with getter and setter.
so let's just say that now i am running a query to retrieve a list of employees. I would like to know how does my application map to my Employee class to my database?
by itself, it doesn't. But add any ORM or similar, and you start to get closer. for example, LINQ-to-SQL (which I mention because it is easy to get working with Visual Studio), you typically get (given to you by the tooling) a custom "data context" class, which you use as:
using(var ctx = new MyDatabase()) {
foreach(var emp in ctx.Employees) {
....
}
}
This is generating TSQL and mapping the data to objects automatically. By default the tooling creates a separate Employee class, but you can tweak this via partial classes. This also supports inserts, data changes and deletion.
There are also tools that allow re-use of your existing domain objects; either approach can be successful - each has advantages and disadvantages.
If you only want to read data, then it is even easier; a micro-ORM such as dapper-dot-net allows you to use our type with TSQL that you write, with it handling the tedious materialisation code.
Your question is a little vague, imo. But what you are referring to is the Model of the MVC (Model-View-Controller) architecture.
What the Model , your Employee Class, manages data of the application. So it can not only get and set (save / update) your data, but it can also be used to notify of a data change. (Usually to the view).
You mentioned you where using SQL, so more then likely you could create and save an entire employee record by sending an Associative Array of the table data to save it to the database. Your setting for the Class would handle the unique SQL syntax to INSERT the data. In larger MVC Frameworks. The Model of your application inherits several other classes to handle the proper saving to different types of backends other than MS SQL.
Models will also, normally, have functions to handle finding records and updating records. This is normally by specify a search field, and it returning the record, of which would include the ID and you would normally base this back into a save / update function to make changes to record. You could also tie into this level of the Model to create revision of the data you are saving
So how the model directly correlates to your SQL structure is dependent on how you right it. Or which Framework you decide to use. I believe a common one for asp.net is the Microsoft's ASP.Net MVC
Your class cannot be directly mapped to the database without ORM tool, The ORM tool will read your configuration and will map your class to DB row as per your mappings automatically. That means you don't need to read the row and set the class fields explicitly but you have to provide mapping files and have to go through the ORM framework to load the entities, and the framework will take care of the rest
You can check nHibernate and here is getting started on nHibernate.