What is the best way to seed data with a lot of information using EntityFramework Core?

asp.net-core asp.net-core-webapi c# database entity-framework-core

Question

I have an entity configuration file and I seed data with the help of HasData, the example below.

public class PublicationConfiguration : IEntityTypeConfiguration<Publication>
    {
        public void Configure(EntityTypeBuilder<Publication> builder)
        {
            builder.Property(p => p.Image)
                .HasMaxLength(256)
                .HasDefaultValue("default-publication.png")
                .IsRequired();

            builder.Property(p => p.Title)
                .HasMaxLength(256)
                .IsRequired();

            builder.Property(p => p.Value)
                .IsRequired();

            builder.Property(p => p.PublisherId)
                .IsRequired();

            builder.Property(p => p.CategoryId)
                .IsRequired();

            builder.HasOne(p => p.Category)
                .WithMany(categ => categ.Publications)
                .OnDelete(DeleteBehavior.Restrict);

            builder.HasOne(p => p.Publisher)
                .WithMany(pub => pub.Publications)
                .OnDelete(DeleteBehavior.Restrict);

            builder.HasData(
                new Publication {
                    Id = "publication-one",
                    Title = "the first publication",
                    Value = "the content of the very first publication on the web-site",
                    CreatedAt = DateTime.Now,
                    CategoryId = "category-one",
                    PublisherId = "publisher-one",
                    Image = "image"
                },
                new Publication
                {
                    Id = "publication-two",
                    Title = "the second publication",
                    Value = "the content of the second publication on the web-site",
                    CreatedAt = DateTime.Now,
                    CategoryId = "category-one",
                    PublisherId = "publisher-two",
                    Image = "image"
                },
                new Publication
                {
                    Id = "publication-three",
                    Title = "the third publication",
                    Value = "the content of the third publication on the web-site",
                    CreatedAt = DateTime.Now,
                    CategoryId = "category-two",
                    PublisherId = "publisher-one",
                    Image = "image"
                }
            );
        }
    }

As you can see I have a property called Value, it's just a string, but I'm going to change it to an array of strings and add some real information meaning Value will contain over a thousand characters, moreover there are only 3 Publications here, but I want to add like 10 more. Thus my seeder will look huge and awful and I do not like it.

So I'd like to move this data anywhere else, maybe to a json file and then read the data from this file or maybe there is a better way, nevertheless I have no idea how I can do this and how to do this right.

The question is, what is the best solution to this problem? And I would be glad to see the solution code.

1
1
3/16/2020 3:40:39 PM

Accepted Answer

You can do multiple data seeds by creating a json file.

Create a new method called SeedLargData in your PublicationConfiguration class.

In this method, get the data in the json file, convert it into List<Publication> , and return it to the Configure method.

 public class PublicationConfiguration : IEntityTypeConfiguration<Publication>
    {
        public void Configure(EntityTypeBuilder<Publication> builder)
        {
           builder.Property(p => p.Image)
            .HasMaxLength(256)
            .HasDefaultValue("default-publication.png")
            .IsRequired();

           builder.Property(p => p.Title)
            .HasMaxLength(256)
            .IsRequired();

           builder.Property(p => p.Value)
            .IsRequired();

           builder.Property(p => p.PublisherId)
            .IsRequired();

           builder.Property(p => p.CategoryId)
            .IsRequired();

           builder.HasOne(p => p.Category)
            .WithMany(categ => categ.Publications)
            .OnDelete(DeleteBehavior.Restrict);

           builder.HasOne(p => p.Publisher)
            .WithMany(pub => pub.Publications)
            .OnDelete(DeleteBehavior.Restrict);

            builder.HasData(SeedLargData());
        }

       public List<Publication> SeedLargData()
        {
            var publications= new List<Publication>();
            using (StreamReader r = new StreamReader(@"json file path"))
            {
                string json = r.ReadToEnd();
                publications= JsonConvert.DeserializeObject<List<Publication>>(json);
            }
            return publications;
        }
    }    
1
3/17/2020 7:03:06 AM

Popular Answer

The answer above works, but I made it reusable.

Here is the result.

public static class SeedHelper
    {
        public static List<TEntity> SeedData<TEntity>(string fileName)
        {
            string currentDirectory = Directory.GetCurrentDirectory();
            string path = "Static/Json";
            string fullPath = Path.Combine(currentDirectory, path, fileName);

            var result = new List<TEntity>();
            using (StreamReader reader = new StreamReader(fullPath))
            {
                string json = reader.ReadToEnd();
                result = JsonConvert.DeserializeObject<List<TEntity>>(json);
            }

            return result;
        }
    }

I hope you understand that "Static/Json" is the path where my json files are located.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow