使用Entity Framework中的导航属性填充多对多关系表 [英] populate many-to-many relationship table using navigation properties in Entity Framework

查看:171
本文介绍了使用Entity Framework中的导航属性填充多对多关系表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在asp.net mvc应用程序中学习实体框架。我有3个模型-



AppModel,CategoryModel和App_CategoryModel(用于指定AppModel和CategoryModel之间的多对多关系)。的摘要是:

 公共类CategoryModel 
{
[Key]
public int id {组; }
公用字串名称{get;组; }
公共虚拟ICollection< App_CategoryModel>映射{get;组; }
}

公共类AppModel
{
[Key]
public int id {get;组; }
公共字符串Name {get;组; }
公共虚拟ICollection< App_CategoryModel>映射{get;组; }
}

公共类App_CategoryModel
{
[Key]
public int id {get; set;}

public int AppId {get;组; }
public int CategoryId {get;组; }

公共虚拟AppModel App {get; set;}
公共虚拟CategoryModel类别{get; set;}
}

我遵循的是代码优先方法,表格创建成功。但是,现在我被困在如何填充和显示此信息上。
我将以下内容作为输入数据:
List< AppModel>
List< CategoryModel> Dictionary< appname,List< CategoryModel>>



我如何继续



此外,想了解这是否是表示数据的正确方法?由于一个应用程序可以具有多个类别-我希望输出是唯一应用程序的集合以及每个应用程序的类别列表,例如:

  Dictionary< AppModel,List< CategoryModel>> 

编辑:
这是我根据建议尝试的来自smoksnes-

  List< CategoryModel> cat_list =新的List< CategoryModel>(); 
CategoryModel c1 =新的CategoryModel();
c1.Name = string1;
cat_list.Add(c1);

CategoryModel c2 =新的CategoryModel();
c2.Name = string2;
cat_list.Add(c2);

List< AppModel> app_list = new List< AppModel>();
AppModel a1 = new AppModel();
a1.Name = app1;
app_list.Add(a1);

AppModel a2 = new AppModel();
a2.Name = app2;
app_list.Add(a2);

a1.mapping.Add(c1);
a1.mapping.Add(c2);
a2.mapping.Add(c1);
a2.mapping.Add(c2);

db.categories.AddRange(cat_list);
db.apps.AddRange(app_list);

db.SaveChanges();

此后,EF发挥了作用-映射表中有2个类别,2个应用程序和4个条目。 / p>

虽然这行得通,但不确定谁阻止EF为类别创建4个条目?

解决方案

就像您的评论中提到的 Barry O´Kane 一样,没有理由保留 App_CategoryModel 模型。 EF将为您管理。仅当它包含有关两个表之间的关系的任何其他信息时,才应保留它。但是根据您的示例,没有理由保留它。

 公共类CategoryModel 
{
public CategoryModel()
{
AppModels = new List< AppModel>();
}

[Key]
public int id {get;组; }
公用字串名称{get;组; }
公共虚拟ICollection< AppModel> AppModels {get;组; }
}

public class AppModel
{
public AppModel()
{
// //不确定是否确实需要这样做。但是EF通常会添加它。
CategoryModels = new List< CategoryModel>();
}

[Key]
public int id {get;组; }
公共字符串Name {get;组; }
公共虚拟ICollection< CategoryModel> CategoryModels {get;组; }
}

关于您的代表权问题,我认为没有必要。由于 AppModel 已经在其模型上连接了 CategoryModel ,因此没有理由使用 Dictionary 。您可以将其存储在 List< AppModel> 中。

  IList < ; AppModel> myApps = context.AppModels.ToList(); 

foreach(myApps中的var myApp)
{
Console.Writeline( App {0}具有以下类别:,myApp.id);
foreach(myApp.CategoryModels中的var类别)
{
Console.Writeline(category.Name);
}
}

当您想向应用程序添加类别时:

  //我不知道如何创建上下文,因此在下面简称为上下文。 
var newCategoryModel = new CategoryModel
{
名称=太棒了!
};
var appModel = context.AppModels.FirstOrDefault(x => x.id == 1);
appModel.CategoryModels.Add(newCategoryModel); // EF会自动为您设置外键...
context.SaveChanges();

如果要确保没有两次添加类别:

  public void AddCategory(int appId,字符串categoryName)
{
using(var context = new DbContext())
{
var category = context.CategoryModels.FirstOrDefault(x => x.Name == categoryName);
if(category == null)
{
//仅创建新的CategoryModel(如果不存在)。
category = new CategoryModel
{
Name = categoryName
};
}
var appModel = new AppModel
{
id = appId
};
//附加以保存到db-trip
context.AppModels.Attach(appModel);

// TODO:可能检查此特定的appModel是否已具有此类别?
appModel.CategoryModels.Add(category);
context.SaveChanges();
}
}


I am learning Entity Framework in asp.net mvc application. I have 3 models -

AppModel, CategoryModel and App_CategoryModel (to specify many to many relationship between AppModel and CategoryModel). A snippet of this is:

public class CategoryModel
    {
        [Key]
        public int id { get; set; }
        public string Name {get; set; }
        public virtual ICollection<App_CategoryModel> mapping { get; set; }
    }

    public class AppModel
    {
        [Key]
        public int id { get; set; }
        public string Name { get; set; }
        public virtual ICollection<App_CategoryModel> mapping { get; set; }
    }

    public class App_CategoryModel
    {
        [Key]
        public int id {get; set;}

        public int AppId {get; set; }
        public int CategoryId {get; set; }

        public virtual AppModel App {get; set;}
        public virtual CategoryModel Category {get; set;}
    }

I was following 'Code-first' approach and the tables got created successfully. But, now I am stuck at how to populate and display this information. I have the following as input data: List<AppModel> List<CategoryModel> and Dictionary<"appname", List<CategoryModel>>

How do I move on from here so that I can update the mapping table?

Also, wanted to understand whether this is the correct approach to represent data. Since an App can have multiple categories - I expect the output as a collection of unique Apps along with a list of categories for each app, something like:

Dictionary<AppModel, List<CategoryModel>>

Edit: This is what I tried as per suggestion from smoksnes-

    List<CategoryModel> cat_list = new List<CategoryModel>();
    CategoryModel c1 = new CategoryModel();
    c1.Name = "string1";
    cat_list.Add(c1);

    CategoryModel c2 = new CategoryModel();
    c2.Name = "string2";
    cat_list.Add(c2);

    List<AppModel> app_list = new List<AppModel>();
    AppModel a1 = new AppModel();
    a1.Name = "app1";
    app_list.Add(a1);

    AppModel a2 = new AppModel();
    a2.Name = "app2";
    app_list.Add(a2);

    a1.mapping.Add(c1);
    a1.mapping.Add(c2);
    a2.mapping.Add(c1);
    a2.mapping.Add(c2);

    db.categories.AddRange(cat_list);
    db.apps.AddRange(app_list);

    db.SaveChanges();

After this, EF worked as expeted - 2 categories , 2 apps and 4 entries in mapping table.

Although this worked, but not sure who is stopping EF to create 4 entries for categories?

解决方案

Just as Barry O´Kane mentioned in your comment there's no reason to keep the App_CategoryModel model. EF will manage this for you. You should only keep it if it contains any extra information regarding the relation between the two tables. But according to your example, there's no reason to keep it.

public class CategoryModel
{
    public CategoryModel()
    {
        AppModels = new List<AppModel>();
    }

    [Key]
    public int id { get; set; }
    public string Name {get; set; }
    public virtual ICollection<AppModel> AppModels { get; set; }
}

public class AppModel
{
    public AppModel()
    {
        // Not sure if this is actually needed anymore. But EF usually adds it.
        CategoryModels = new List<CategoryModel>();
    }

    [Key]
    public int id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<CategoryModel> CategoryModels { get; set; }
}

And regarding your question about representation, I don't think it's necessary. Since the AppModel already has the connected CategoryModel on it's model there's no reason for a Dictionary. You can store it in a List<AppModel> instead.

IList<AppModel> myApps = context.AppModels.ToList();

foreach (var myApp in myApps)
{
    Console.Writeline("App {0} has the following categories:", myApp.id);
    foreach (var category in myApp.CategoryModels)
    {
        Console.Writeline(category.Name);
    }
}

And when you want to add a category to an app:

// I don't know how you create your Context, so below it's just called context.
var newCategoryModel = new CategoryModel
{
    Name = "SO is awesome!"
};
var appModel = context.AppModels.FirstOrDefault(x => x.id == 1);
appModel.CategoryModels.Add(newCategoryModel); // EF will automatically set foreign keys for you...
context.SaveChanges();

And if you want to make sure that no category is added twice:

public void AddCategory(int appId, string categoryName)
{
    using(var context = new DbContext())
    {
        var category = context.CategoryModels.FirstOrDefault(x => x.Name == categoryName);
        if(category == null)
        {
            // Only create new CategoryModel if it doesn't exist.
            category = new CategoryModel
            {
                Name = categoryName
            };
        }
        var appModel = new AppModel
        {
            id = appId
        };
        // Attach to save on db-trip
        context.AppModels.Attach(appModel);

        //TODO: Possibly check if this particular appModel already has this category?
        appModel.CategoryModels.Add(category);
        context.SaveChanges();
    }
}

这篇关于使用Entity Framework中的导航属性填充多对多关系表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆