Brief
We will develop simple Database Call (SQL Server) using EntityFramework using the Fluent API.We will have below things for the DB Cal.
- Student Class
- StudentMap Class
- PracticeContext Class
- DataBaseCall Class
- Proram Class
- app.config (In web development, we have web.config)
Student Class:
namespace DotnetConsole
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
}
}
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
}
}
StudentMap Class
This class is required since fluent api is creating table from the configuration.
{
public StudentMap()
{
this.ToTable("Student");
this.Property(s => s.ID).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
this.Property(s => s.Name);
}
}
PracticeContext Class:
public class PracticeContext: DbContext{
public PracticeContext(): base() {}
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
modelBuilder.Configurations.AddFromAssembly(assembly);
}
}
}
DataBaseCall Class:
public class DataBaseCall{
public static List<Student> GetStudents()
{
return Execute((context) =>
{
var students = context.Students.ToList();
if (students != null && students.Count() > 0)
{
Console.WriteLine($"Student ID : Student Name");
foreach (Student student in students)
{
Console.WriteLine($"{student.ID} : {student.Name}");
}
}
return students;
});
}
private static TResult Execute<TResult>(Func<PracticeContext, TResult> func)
{
try
{
return func(new PracticeContext());
}
catch (SqlException ex)
{
Console.WriteLine(ex);
throw new Exception("Error Occured.");
}
}
}
Program Class
class Program{
static void Main(string[] args)
{
try
{
DataBaseCall.GetStudents();
}
catch(Exception ex)
{
Console.WriteLine("Error occured while performing student operation.", ex);
}
Console.ReadKey();
}
}
App.config file:
Highlighted things are mandatory:- entityFramework: Install it from the Nuget Package Manager
- PracticeContext: The name of the dbcontext class which we have created above.
- DESKTOP: Name of the machine to which you are connecting for local you may use dot(.)
- Practice: Name of the database to which you are connecting.
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="PracticeContext" connectionString="Data Source=DESKTOP;Initial Catalog=Practice;User ID=xxx;Password=xxx" providerName="System.Data.SqlClient" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
Output:
Problem
The problem with the above code is that when ever we add any properties to the Student Model the below error will be thrown.The model backing the PracticeContext context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
To resolve this we can choose either of these two:
- We need to add the code as below to the Main Method in Program.cs.
- This approach will delete everything from the database and recreate everything again from the scratch.
static void Main(string[] args)
{
try
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<PracticeContext>())
DataBaseCall.GetStudents();
}
catch(Exception ex)
{
Console.WriteLine("Error occured while performing student operation.", ex);
}
Console.ReadKey();
}
- Or, We can do as below: This approach will only update the database with the latest changes without impacting the existing things.
- Run the command in Package Manager Console Enable-Migrations
- This command has added a Migrations folder to our project. This new folder contains two files:
- The Configuration class (Configuration.cs)
- An InitialCreate migration
- We need to add the code as below to the Main Method in Program.cs.
static void Main(string[] args)
{
try
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<PracticeContext, Configuration>());
DataBaseCall.GetStudents();
}
catch(Exception ex)
{
Console.WriteLine("Error occured while performing student operation.", ex);
}
Console.ReadKey();
}
Configuration.cs
The file code looks as below:
internal sealed class Configuration : DbMigrationsConfiguration<DotnetConsole.PracticeContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(DotnetConsole.PracticeContext context)
{
// This method will be called after migrating to the latest version.
{
// 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.
}
}
// to avoid creating duplicate seed data.
}
}
Do it with async and await
- Repository.cs
{
private PracticeContext context = null;
public DbSet<T> Entities => this.context.Set<T>();
public IQueryable<T> Table => this.Entities;
public Repository(PracticeContext context)
{
this.context = context;
}
public async Task<List<T>> InsertListAsync(List<T> entites)
{
try
{
List<T> t = this.Entities.AddRange(entites).ToList();
await this.context.SaveChangesAsync();
return t;
}
catch (DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
msg += string.Format("Property: {0} Error: {1}{2}", validationError.PropertyName, validationError.ErrorMessage, Environment.NewLine);
}
}
var fail = new Exception(msg, dbEx);
//Debug.WriteLine(fail.Message, fail);
throw fail;
}
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
- DataBaseCall.cs
{
try
{
return await ExecuteAsync<T, List<T>>(async (repository) =>
{
return await repository.InsertListAsync(list);
});
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
private async static Task<TResult> ExecuteAsync<T, TResult>(Func<Repository<T>, Task<TResult>> func) where T : class
{
using (PracticeContext context = new PracticeContext())
{
try
{
return await func(new Repository<T>(context));
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw new Exception("Error Occured.");
}
}
}
Program.cs
static void Main(string[] args)
{
DataBaseCallMethod();
Console.ReadKey();
}
private static async void DataBaseCallMethod()
{
try
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<PracticeContext, Migrations.Configuration>());
var students = new List<Student>();
var results = await DataBaseCall.InsertListAsync(students);
}
catch(Exception ex)
{
Console.WriteLine("Error occured while performing student operation.", ex.ToString());
}
}
Please refer below link for details.
Comments
Post a Comment