我有一个场景需要一些帮助。
让我们假设有一个用户听某种类型的音乐。
class User
{
public virtual List<UserMusicType> Music { get; set; }
}
public class UserMusicType
{
public int ID { get; set; }
public MusicType name { get; set; }
}
public class MusicType
{
public int ID { get; set; }
public string Name { get; set; }
}
有一个表格,我要求用户检查/选择他听的所有类型的音乐。他选择了3种类型,即{Pop,Rock和Electronic}
案例1:
现在我想更新用户实体并插入这3种新类型。根据我的理解,我需要首先删除数据库中保存此用户的任何MusicTypes,然后再次插入这些新类型。这是一种正确的方法吗?删除所有以前的和插入新的?或者其他任何方式吗?
案例2:
我正在将MusicType名称作为字符串。现在,在更新用户实体时,我必须首先获取MusicType.ID,之后我将能够执行此操作:
user.Music.Add(new UserMusicType() { ID = SOME_ID });
这种情况有更好的方法吗?
我很乐意收到EF有经验的人的回复。我想知道是否有一种有效的方法。或者即使我的方法/模型完全错误或者可以改进。
答案 0 :(得分:1)
第一个问题:
实际上,这是个人偏好。因为,不希望删除属于该用户的所有行,然后插入它们。我会将从表单发布的集合与存储在数据库中的行进行比较。然后,从数据库中删除那些不再存在于集合中的实体。并且,插入新的。甚至,您可以更新那些修改了一些其他细节的实体。
顺便说一句,您可以使用新发布的EntityGraphOperations实体框架代码优先轻松实现此目的。我是这个产品的作者。我已将其发布在github,code-project和nuget中。借助InsertOrUpdateGraph
方法,它会自动将您的实体设置为Added
或Modified
。在DeleteMissingEntities
方法的帮助下,您可以删除数据库中存在的实体,但不能删除当前集合中的实体。
// This will set the state of the main entity and all of it's navigational
// properties as `Added` or `Modified`.
context.InsertOrUpdateGraph(user)
.After(entity =>
{
// And this will delete missing UserMusicType objects.
entity.HasCollection(p => p.Music)
.DeleteMissingEntities();
});
您可以通过逐步演示阅读my article on Code-project,并准备下载示例项目。
第二个问题:
我不知道您在哪个平台上开发应用程序。但是,通常我将这些库存储为缓存中的MusicType
。并使用DropDownList
元素渲染所有类型。当用户发布表单时,我得到的是值而不是所选类型的名称。因此,不需要额外的工作。
答案 1 :(得分:1)
首先,您不需要UserMusicType
类,您可以将`User class声明为
class User
{
public virtual List<MusicType> Music { get; set; }
}
实体框架将在数据库中创建多对多的关系表
至于第一个问题,这取决于。如果您在其他任何地方使用此关系,例如付款或审计跟踪,那么最好的方法是将发布的值与保存的值进行比较,例如:
用户首次选择音乐1,音乐2,音乐3并保存,在这种情况下将插入3条记录。 用户编辑了他的选择并选择了音乐1,音乐3,音乐4,在这种情况下,您将获得提交的值1,3,4并检索存储在数据库中的值1,2,3 然后你将获得新值,这些值是新值中存在但不存在的值,在这种情况下它将是4
您将获得已删除的值,这些值存在于旧的但不是新的中,在这种情况下它将是Music 2。 其余的可以忽略不计。
因此,您的查询将添加音乐4,删除音乐2。
如果您不依赖于这种关系,那么删除所有用户音乐并再次添加该集合会更容易。
至于问题的第二部分,我假设您将为用户显示一些chechbox,您应该将复选框控件的值设为MusicType
ID,这将是发布到后端,您可以使用它将其链接到用户。
例如:
user.Music.Add(new MusicType{ID=[selected ID ]}
您不应该依赖音乐名称