简体   繁体   中英

How to associate entities during seed with Entity Framework

I have these classes:

[Serializable]
public class Module
{
        [Key]
        public int Id { get; set; }
        public string ModuleName { get; set; }
        public string FontAwesomeClass { get; set; }
}

[Serializable]
public class ModulosPorUsuario
{
        public string Email { get; set; }
        public List<Module> Modules{ get; set; }
}

And I need to seed like this:

#region Seed Modules
    context.Modulos.Add(new Module() { Id = 1, ModuleName = "Contabilidad", FontAwesomeClass = "fa-ambulance" });
    context.Modulos.Add(new Module() { Id = 2, ModuleName = "Recursos Humanos", FontAwesomeClass = "fa-heartbeat" });
    context.Modulos.Add(new Module() { Id = 3, ModuleName = "Inventario", FontAwesomeClass = "fa-anchor" });
    context.Modulos.Add(new Module() { Id = 3, ModuleName = "Produccion", FontAwesomeClass = "fa-binoculars" });
    context.Modulos.Add(new Module() { Id = 3, ModuleName = "Ventas", FontAwesomeClass = "fa-coffee" });
    context.Modulos.Add(new Module() { Id = 3, ModuleName = "Compras", FontAwesomeClass = "fa-calendar-o" });
    context.Modulos.Add(new Module() { Id = 3, ModuleName = "Cotizaciones", FontAwesomeClass = "fa-building" });
    #endregion

However my question is how can I associate a list of modules that were previously seeded??

    #region Seed ModulosPor Usuario
    context.ModulosPorUsuario.Add(new ModulosPorUsuario()
    {
        Email = "companyadmin@xx.onmicrosoft.com",
        Modules = ???
    });

    #endregion

Update 1:

When I check the tables created for me this doesnt look right. A module is an entity by its own, and ModulesPeruser should be a relationship between email and many different modules. However on the Module table it created a foreign key to ModulesPerUser.

What is wrong with my design? http://screencast.com/t/Z0u2950zm

var module1 = new Module() { Id = 1, ModuleName = "Contabilidad", FontAwesomeClass = "fa-ambulance" };
context.Modulos.Add(module);
context.ModulosPorUsuario.Add(new ModulosPorUsuario()
{
    Email = "companyadmin@xx.onmicrosoft.com",
    Modules = new List<Module>(){module1, module2 etc...};
});

您可以保存模块列表,并在调用dbContext.SaveChanges()将该集合分配给modulosPorUsuario对象,然后再次保存更改。

var modules = new List<Module>()
{
    new Module() { Id = 1, ModuleName = "Contabilidad", FontAwesomeClass = "fa-ambulance" },
    new Module() { Id = 2, ModuleName = "Recursos Humanos", FontAwesomeClass = "fa-heartbeat" },
    new Module() { Id = 3, ModuleName = "Inventario", FontAwesomeClass = "fa-anchor" },
    new Module() { Id = 4, ModuleName = "Produccion", FontAwesomeClass = "fa-binoculars" },
    new Module() { Id = 6, ModuleName = "Ventas", FontAwesomeClass = "fa-coffee" },
    new Module() { Id = 7, ModuleName = "Compras", FontAwesomeClass = "fa-calendar-o" },
    new Module() { Id = 8, ModuleName = "Cotizaciones", FontAwesomeClass = "fa-building" }
};

context.ModulosPorUsuario.Add(new ModulosPorUsuario()
{
    Email = "companyadmin@xx.onmicrosoft.com",
    Modules = modules
});

context.SaveChanges();

Couple of things to be aware of:

  1. Seeding runs every time you update the database. As a result, you should use AddOrUpdate , rather than Add , to keep from adding the same items multiple times.

  2. When using AddOrUpdate , only simple data types are updated (string, int, etc.). Properties referencing class instances or list properties will not be updated.

To get around the second point, you should update id properties rather than reference properties. For example, given the following:

public class Foo
{
    public int Id { get; set; }

    public string Name { get; set; }

    public int BarId { get; set; }
    public virtual Bar Bar { get; set; }
}

public class Bar
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Foo> Foos { get; set; }
}

You would need to structure your seed like:

var bar1 = new Bar { Name = "Bar 1" };
var bar2 = new Bar { Name = "Bar 2" };
var bar3 = new Bar { Name = "Bar 3" };

context.Bars.AddOrUpdate(
    r => r.Name,
    bar1,
    bar2,
    bar3
 );

 context.SaveChanges();

 context.Foos.AddOrUpdate(
     r => r.Name,
     new Foo
     {
         Name = "Foo",
         BarId = bar1.Id
     }
  );

That way, if you want to change the Bar instance, the Foo is associated with, you can. If you were to use Bar = bar1 instead, it would be ignored on update.

The same goes for your list properties. In a one-to-many situation, you should set the relationship on the principal side as in the sample code above, rather than setting the list property directly, Bar.Foos in this example.

In a many-to-many, you simply won't be able to update the relationship, since both sides have a collection and you don't have any access to the join table. You can initially seed the relationships, but you won't be able to update them in future seeds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM