实体框架更新多对多的关系:虚拟与否 [英] entity framework update many to many relationship: virtual or not

查看:184
本文介绍了实体框架更新多对多的关系:虚拟与否的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直使用EF4(未code-第一),因为一年的时间,所以我没有真正与它的专家。
我用多对许多关于保存n更新的关系已经毋庸置疑。

I've been using EF4 (not code-first) since a year, so I'm not really an expert with it. I've a doubt in using many-to-many relationship regarding save n update.

我读到某处计算器上(我找不到网址了)一个解决方案 - 更新现有的许多一对多的关系 - 是不会宣布虚拟财产;但是,如果我这样做的方式,发动机不能用便于装载装载dataas。

I read somewhere on stackoverflow (i can't find the url anymore) that one solution - to update an existing many-to-many relation - is to not declare "virtual" property; but, if i do this way, the engine can't load dataas with easy loading.

你能解释一下请我的原因吗? Otherwire,请你帮我在这个主题寻找一些很酷的文档?

Can you pls explain me the reason? Otherwire, could you please help me in finding some cool docs on this theme?

THX

推荐答案

您可以更新一个多一对多的关系这种方式(如这给用户3角色5为例):

You can update a many-to-many relationship this way (as an example which gives user 3 the role 5):

using (var context = new MyObjectContext())
{
    var user = context.Users.Single(u => u.UserId == 3);
    var role = context.Roles.Single(r => r.RoleId == 5);

    user.Roles.Add(role);

    context.SaveChanges();
}

如果在 User.Roles 收集被声明为虚拟 user.Roles 。新增(角色); 确实会触发延迟加载,这意味着的所有的为用户角色首先从数据库中添加新角色之前加载

If the User.Roles collection is declared as virtual the line user.Roles.Add(role); will indeed trigger lazy loading which means that all roles for the user are loaded first from the database before you add the new role.

这其实是令人不安的,因为你并不需要加载整个角色集合添加一个新的角色给用户。

This is in fact disturbing because you don't need to load the whole Roles collection to add a new role to the user.

但是,这并不意味着你必须删除虚拟关键字和完全放弃懒加载。你可以关闭延迟加载在这种具体情况:

But this doesn't mean that you have to remove the virtual keyword and abandon lazy loading altogether. You can just turn off lazy loading in this specific situation:

using (var context = new MyObjectContext())
{
    context.ContextOptions.LazyLoadingEnabled = false;

    var user = context.Users.Single(u => u.UserId == 3);
    var role = context.Roles.Single(r => r.RoleId == 5);

    user.Roles = new List<Role>(); // necessary, if you are using POCOs
    user.Roles.Add(role);

    context.SaveChanges();
}

修改

如果您想更新我会preFER与预先加载加载原始角色的用户的整个角色集合(= 包含)。你需要这个名单反正可能删除一些角色,所以你不需要等到延迟加载从数据库中获取它们:

If you want to update the whole roles collection of a user I would prefer to load the original roles with eager loading ( = Include). You need this list anyway to possibly remove some roles, so you don't need to wait until lazy loading fetches them from the database:

var newRolsIds = new List<int> { 1, 2, 5 };
using (var context = new MyObjectContext())
{
    var user = context.Users.Include("Roles")
        .Single(u => u.UserId == 3);
    // loads user with roles, for example role 3 and 5

    var newRoles = context.Roles
        .Where(r => newRolsIds.Contains(r.RoleId))
        .ToList();

    user.Roles.Clear();
    foreach (var newRole in newRoles)
        user.Roles.Add(newRole);

    context.SaveChanges();
}

而不是从你还可以将它们,因为你在这个例子中知道密钥属性值的数据库加载新的角色。您还可以删除完全缺失的角色,而不是清除整个收集和代替重新添加已有的角色:

Instead of loading the new roles from the database you can also attach them since you know in the example the key property value. You can also remove exactly the missing roles instead of clearing the whole collection and instead of re-adding the exisiting roles:

var newRolsIds = new List<int> { 1, 2, 5 };
using (var context = new MyObjectContext())
{
    var user = context.Users.Include("Roles")
        .Single(u => u.UserId == 3);
    // loads user with roles, for example role 3 and 5

    foreach (var role in user.Roles.ToList())
    {
        // Remove the roles which are not in the list of new roles
        if (!newRoleIds.Contains(role.RoleId))
            user.Roles.Remove(role);
        // Removes role 3 in the example
    }

    foreach (var newRoleId in newRoleIds)
    {
        // Add the roles which are not in the list of user's roles
        if (!user.Roles.Any(r => r.RoleId == newRoleId))
        {
            var newRole = new Role { RoleId = newRoleId };
            context.Roles.Attach(newRole);
            user.Roles.Add(newRole);
        }
        // Adds roles 1 and 2 in the example
    }
    // The roles which the user was already in (role 5 in the example)
    // have neither been removed nor added.

    context.SaveChanges();
}

这篇关于实体框架更新多对多的关系:虚拟与否的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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