Thursday, December 17, 2020

Performing seed data to database from JSON using reflection

We can work with two approaches in Asp.Net MVC i.e., DB first approach and Code first approach. Apart from that, we can also work with different ORM models such as Entity framework, NHibernate, etc.

In the code first approach, database create with the migration is simple and easy task to add, update, and delete the data. It helps seed database simply, just add the properties and call the Savechanges method.

We can initialize the code first generated database with the values from JSON using data access layer and reflection. By the way, JSON is considered as the best data format as it gives clean and clear data result. We can apply other formats to the same approach but JSON is used for the ease and the availability of the large and optimal JSON.NET library from Newtonsoft.

What is Reflection in core?

Reflection allows us to get information about the assemblies and type defined within them such as classes, interface, structure, and enumerations.

Using reflection, we can dynamically instantiates the objects, access the fields, methods, properties. Reflection can lower down the performance. If we accessed the fewer objects with reflection then we will not notice the execution speed. Let’s take a simple example to understand it.

private static void NormalGet()
{
      var instance = new Customer();
      for (int i = 0; i < 10000; i++)
      {
           var value = instance.Name;
      }
}
private static void ReflectionGet()
{
var instance = new Customer();
var type = instance.GetType();
for (int i = 0; i < 10000; i++)
{
            var value = type.GetProperty("Name").GetValue(instance);
       }
}

The execution time for the first one method is faster than the reflection get method. So the best way is to not use the reflection with our project as it will significantly reduce the performance.

Seeding with JSON data

Step 1: Add JSON file

Now we will add the JSON file with the name Customer.json as follows. Here we have the simple data with three to four property (Name, order, item).

{
  "Customer": [
    {
      "Name": "Raj",
      "Order": 1,
      "Item": [
        {
          "ItemName": "Book"
        },
        {
          "ItemName": "Machine"
        }
      ]
    },
   {
      "Name": "Lokesh",
      "Order": 2,
      "Item": [
        {
          "ItemName": "Phone"
        },
        {
          "ItemName": "Laptop"
        }
      ]
    },
    {
      "Name": "Jay",
      "Order": 2,
      "Item": [
        {
          "ItemName": "Pen"
        },
        {
          "ItemName": "Book"
        }
      ]
}
]
}

Now we will use this code to seed the database. We are calling it from the start up file in configure method in asp.net core.

Step 2: Update Startup file

Now we will update the configure method in the startup file. In which we will read the file with System.IO.File.ReadAllText. After that we will add the json text in seed method as follows. In the read all text we have passed our JSON file.

public void Configure (IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
         app.UseDeveloperExceptionPage();
    }
    else
    {
         app.UseExceptionHandler("/Home/Error");
         app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseMvc(routes =>
   {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
        });
        var jsontext = System.IO.File.ReadAllText(@"Customer.json");
        Seeding.Seed(jsontext, app.ApplicationServices);
}

Step 3: create the Seeding class

In this class, we will define the Seed method in it which is used for the deserialize the JSON file into the list of Customer object. After that we have used here the asp.net core service provider to get services from the startup file. In the deserialize object we have pass the json data and json serialize setting object into the list of customer.

using JsonNet.PrivateSettersContractResolvers;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; 
namespace WebApplication18.Models
{
    public class Seeding
    {
        public static void Seed(string jsonData,
                            IServiceProvider serviceProvider)
        {
            JsonSerializerSettings settings = new JsonSerializerSettings
            {
                ContractResolver = new PrivateSetterContractResolver()
            };
            List<Customer> customer =
             JsonConvert.DeserializeObject<List<Customer>>(
               jsonData, settings);
            using (
             var serviceScope = serviceProvider
               .GetRequiredService<IServiceScopeFactory>().CreateScope())
            {
                var context = serviceScope
                              .ServiceProvider.GetService<Context>();
                if (!context.customers.Any())
                {
                    context.AddRange(customer);
                    context.SaveChanges();
                }
            }
        }
    }
}

After that call the addrange method into the customer and performed the savechanges method.

Let’s take another example by seeding the database using has data.

Seeding using has data

Step 1: Create model

Here we take the two model named Item and Customer as shown below. In which Customer id is the foreign key in the Item table.

public class Item
    {
        public int ItemId { get; set; }
        public string ItemName { get; set; }
        public int CId { get; set; }
        public Customer customer { get; set; }
    }
public class Customer
    {
        public int CId { get; set; }
        public string Name { get; set; }
        public int Order { get; set; }
        public List<Item> items { get; set; } => new List<Item>();
    }

Step 2: Update context file

Here we have to override the onmodelcreating method and fill the data in it. We can use it for adds multiple rows at a time. Migration can automatically compute the operation while updating the database of the model.

public class Context : DbContext
    {
        public Context(DbContextOptions options) : base(options)
        {
        }
        public DbSet<Customer> customers { get; set; }
        public DbSet<Item> items { get; set; }
        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Customer>().HasData(
                new Customer { CId = 1, Name = "Raj", Order = 1 }
            );
            builder.Entity<Item>().HasData(
                new Item { CId = 1, ItemId = 1, ItemName = "Phone" },
                new Item { CId = 1, ItemId = 2, ItemName = "Second post" }
            );
        }
    }

Step 3: Create the controller

Create the controller to get the data from the two models.

[Route("api/[controller]")]
    [ApiController]
    public class HomeController : Controller
    {
         private readonly Context _db;
         public HomeController(Context db) => _db = db;
         // GET api/values
         [HttpGet]
         public ActionResult<IEnumerable<Customer>> Get()
         {
             return _db.customers
                 .Include(b => b.items)
                 .ToList();
         }
         // GET api/values/5
         [HttpGet("{id}")]
         public ActionResult<Customer> Get(int id)
         {
             return _db.customers
                 .Include(b => b.items)
                 .SingleOrDefault(b => b.CId == id);
         }
}

If you have large data file like JSON then you can go through as below. Just add a new method and call the json file from where it is placed and read that file using reader.

protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Customer>().HasData(
                new Customer { CId = 1, Name = "Raj", Order = 1 }
            );
            builder.Entity<Item>().HasData(itemvalue());
              
        }
        public List<Item> itemvalue()
        {
            var itemvalue = new List<Item>();
            using (StreamReader r = new StreamReader(@"json file path"))
            {
                string json = r.ReadToEnd();
                itemvalue = JsonConvert.DeserializeObject<List<Item>>(json);
            }
            return itemvalue;
        }

Conclusion:

In this blog, we have seen the programming concepts of how to seed the database using json and has data. Seeding using json is as simpler as you seen. First of all, we have to see the reflection but it consumes the execution time. So we have done with JSON file normally just write the file and call it in the startup file. Seeding using the JSON file, will turn our code lighter and simpler.

 

The post Performing seed data to database from JSON using reflection appeared first on Simple Talk.



from Simple Talk https://ift.tt/3nt4izx
via

No comments:

Post a Comment