0

I am working on a school project using ASP.NET MCV4, EF6, Code-First models. Now, I am wondering how should I fill the database with sample data. I checked migrations, but I don't want to mess with the db structure. I just want to insert data, I tried this:

namespace Autokereskedes.Models
{
    public class _SampleData : DropCreateDatabaseIfModelChanges<AutoDb>
    {
        protected override void Seed(AutoDb context)
        {
            new Autokereskedes.Models.SampleData.Users().List().ForEach(u=>context.Users.Add(u));

            new Autokereskedes.Models.SampleData.Cars().List().ForEach(c => context.Cars.Add(c));

        }
    }
}

namespace Autokereskedes.Models.SampleData
{
    public class Users
    {
        public List<User> List()
        {
            var crypto = new SimpleCrypto.PBKDF2();
            var salt = Autokereskedes.Controllers.AccountController.PasswordSalt;
            return new List<User> 
            {
                new User { 
                    UserId = Guid.NewGuid(), 
                    Email = "admin@autoker.hu", 
                    Password = crypto.Compute("admin",salt),
                    Phone = "+36 20 XXX YYZZ",
                    Banned = false,
                    Country = "Hungary",
                    City = "Szeged",
                    Street = "DivisonByZero street 1/0",
                    ZipCode = 1100,
                    RegistrationDate = DateTime.Now
                },
                new User { 
                    UserId = Guid.NewGuid(), 
                    Email = "user@autoker.hu", 
                    Password = crypto.Compute("user",salt),
                    Phone = "+36 20 XXX YYZZ",
                    Banned = false,
                    Country = "Hungary",
                    City = "Szeged",
                    Street = "DivisonByZero street 2/0",
                    ZipCode = 1100,
                    RegistrationDate = DateTime.Now
                }
            };
        }
    }
}

It is working, I thought. But how should I insert data that has foreign keys? I saw a tutorial where they used a single file for all the List<>-s and in the foreign key field used something like this: Genre = genres.Single(g => g.Name == "Jazz"). I can't really copy that now.

namespace Autokereskedes.Models.SampleData
{
    public class Cars
    {
        public List<Car> List()
        {
            return new List<Car>
            {
                new Car {
                    CarId = Guid.NewGuid(),
                    DepoId = now what
                },
                new Car {

                }
            };
        }
    }
}
Yuck
  • 49,664
  • 13
  • 105
  • 135
szab.kel
  • 2,356
  • 5
  • 40
  • 74
  • First you need to insert the primary entity from the relation, in this case "DepoId", save that DepoId in a global variable in the class and then pass it to Car.DepoId. You could also use this http://stackoverflow.com/questions/8448087/how-to-seed-data-using-entityframework-code-first-migrations – Guillermo Oramas R. Nov 06 '13 at 12:40
  • You could / should use the "Seed" method in the Migrations.Configuration.cs file - this method is exactly made for your purpose. – Christian Sauer Nov 06 '13 at 12:42

3 Answers3

2

When you seed the data, you need to account for the foreign key relationships... eventually.

return new List<Car>
{
    new Car {
        CarId = Guid.NewGuid(),
        DepoId = now what // it depends, is this a required relationship?
    },
    new Car {
    }
};

If DepoId is an optional relationship, you can just wait until you have a Depo & DepoId before setting up this property. Otherwise if it is required, you need to set it up before you insert it into the context.

protected override void Seed(AutoDb context)
{
    new Autokereskedes.Models.SampleData.Users().List()
        .ForEach(u=>context.Users.Add(u));
    var cars = new Autokereskedes.Models.SampleData.Cars().List();
    var depos = new Autokereskedes.Models.SampleData.Depos().List();
    foreach (var car in cars)
    {
        car.DepoId = depos.FirstOrDefault(x => x.DepoId == ...?);

        context.Cars.Add(car);
    }
}

I suppose the question is, how do you decide which depo should be assigned to each car?

Another way to do it, since your Depo entities are a dependency and you need to resolve them first, would be to pass your depos to your cars list method:

var depos = new Autokereskedes.Models.SampleData.Depos().List();
depos.ForEach(d => context.Depos.Add(d));
//context.SaveChanges(); no need for this since your id's are Guid's
var cars = new Autokereskedes.Models.SampleData.Cars().List(depos);

public List<Car> List(IEnumerable<Depo> depos)
{
    // now you have depos to look for id's in
    return new List<Car>
    {
        new Car {
            CarId = Guid.NewGuid(),
            DepoId = depos.SingleOrDefault(x => [your predicate]),
        },
        new Car {
        }
    };
}
danludwig
  • 46,965
  • 25
  • 159
  • 237
  • There are other ways you could do it, and given circumstances sometimes, other ways you would have to do it. I don't know enough about your domain model relationships to provide any further guidance. – danludwig Nov 06 '13 at 13:03
  • Yeah, It is hard to provide every information in the question, but passing the related lists as an argument seems like a good solution. I just have to care, not to mess up the order. And yes, the original question was how should I refer to a guid in my lists. – szab.kel Nov 06 '13 at 13:08
0

The process is called "seeding" the data.

You create an initializer object and override the Seed method:

public class MyDataContextDbInitializer : DropCreateDatabaseIfModelChanges<MyDataContext>
{
   protected override void Seed(MagazineContext context)
   {
     context.Customers.Add(new Customer() { CustomerName = "Test Customer" });
   }
} 

Here is an article describing how to do it: http://www.codeproject.com/Articles/315708/Entity-Framework-Code-First-Data-Initializers

Bogdan Gavril MSFT
  • 20,615
  • 10
  • 53
  • 74
0

I made an Nuget package, so you can generate random contact data (firstname, lastname, city, zipcode, birthdates, accountnumbers, etc)

In this version you can export to CSV, XML, JSON and SQL.

Open Visual Studio, Manage Nuget Packages Search online for:

DSharp FrameWork: ContactGenerator

Any suggestions for extending functionality are welcome.

Erwin Bakels
  • 184
  • 1
  • 8