Kot*_*otu 0 linq asp.net-mvc orm many-to-many repository-pattern
我在保存对数据库的更改方面存在问题,我正在使用LINQ2SQL映射.我已经基于以下教程实现了M:M关系(User <= UserRole => Role):http://www.codeproject.com/KB/linq/linqtutorial2.aspx#premain25
当我使用一个继承自DataContext并负责我所有域类的类时,一切正常,例如:
[数据库]公共类BookCatalog:DataContext {//创建静态DataContext以删除M:M Join记录私有静态DataContext contextForRemovedRecords = null;
public BookCatalog() : base("Data Source=KO2\\SQLSERVER;Initial Catalog=Katalog;Integrated Security=True") { }
public Table<User> Users;
public Table<Role> Roles;
public Table<UserRole> UserRoles;
public static void RemoveRecord<T>(T recordToRemove) where T : class
{
// Use the static contextForRemovedRecords
if (contextForRemovedRecords == null)
contextForRemovedRecords = new BookCatalog();
Table<T> tableData = contextForRemovedRecords.GetTable<T>();
var deleteRecord = tableData.SingleOrDefault(record => record == recordToRemove);
if (deleteRecord != null)
{
tableData.DeleteOnSubmit(deleteRecord);
}
}
// NEW method (not part of LINQ to SQL) to cancel changes
public void CancelChanges()
{
if (contextForRemovedRecords != null)
{
contextForRemovedRecords = null;
}
}
// Override DataContext's SubmitChanges() to handle any removed records
public new void SubmitChanges()
{
if (contextForRemovedRecords != null)
{
contextForRemovedRecords.SubmitChanges();
}
base.SubmitChanges();
}
Run Code Online (Sandbox Code Playgroud)
}
不幸的是,由于某些原因,我需要在我的项目中保留单独的存储库.其中一个例子:
公共类SqlRolesRepository:IRolesRepository {
private Table<Role> rolesTable;
public SqlRolesRepository(string connectionString)
{
rolesTable = (new DataContext(connectionString)).GetTable<Role>();
}
public IQueryable<Role> Roles
{
get { return rolesTable; }
}
public void SaveRole(Role role)
{
bool ins = false;
if (rolesTable.Any(m => m.RoleID == role.RoleID))
{
rolesTable.Context.Refresh(RefreshMode.KeepCurrentValues, role);
}
else
{
try { rolesTable.InsertOnSubmit(role); ins = true; }
catch (Exception ex)
{
throw ex;
}
}
try
{
rolesTable.Context.SubmitChanges();
}
catch (SqlException ex)
{
if (ins) rolesTable.DeleteOnSubmit(role);
List<ErrorInfo> errors = new List<ErrorInfo>();
if (ex.Message.Contains("UNQ_RoleName"))
errors.Add(new ErrorInfo("RoleName", "Rola o takiej nazwie ju? istnieje", role));
if (errors.Any()) throw new RulesException(errors);
throw;
}
}
public void SaveChanges()
{
rolesTable.Context.Refresh(RefreshMode.OverwriteCurrentValues);
rolesTable.Context.SubmitChanges();
}
public void DeleteRole(Role role)
{
rolesTable.DeleteOnSubmit(role);
rolesTable.Context.SubmitChanges();
}
public void DeleteRole(string roleName)
{
rolesTable.DeleteOnSubmit(rolesTable.FirstOrDefault(m => m.Name == roleName));
rolesTable.Context.SubmitChanges();
}
public Role GetRoleByName(string name)
{
return rolesTable.Single(m => m.Name == name);
}
public string[] GetAllRoles(){
return (from rola in rolesTable
select rola.Name).ToArray();
}
Run Code Online (Sandbox Code Playgroud)
}
关键是当我想要保存更改时:
(...)
foreach (string roleName in roleNames)
{
Role rola = _RolesRepository.GetRoleByName(roleName);
if (rola != null)
{
foreach (string userName in usernames)
{
User usr = _UsersRepository.GetUserByName(userName);
if (usr != null)
{
if (!rola.Users.Contains(usr))
{
rola.Users.Add(usr);
}
}
}
_RolesRepository.SaveChanges();
}
}
(...)
Run Code Online (Sandbox Code Playgroud)
LINQ尝试再次保存类User的实例,而不是保存关联类的实例(UserRole),出现SqlExcepiton错误(用户名列上的唯一键).在调试模式中,我注意到用户实例似乎以某种方式加倍...
我的LINQ类映射如教程(上面列出的链接),示例项目可在此处获得:http://www.codeproject.com/KB/linq/linqtutorial2/linqtutorial2_src.zip
也许有人会知道如何将它与存储库模式(多个存储库)一起使用.我正在阅读MSDN文章(http://msdn.microsoft.com/en-us/library/bb425822.aspx),似乎从我的SqlRolesRepository调用SubmitChanges()应该正确更新数据库,但它不是.. .
您通过让每个存储库封装自己的数据上下文实例/表引用来打破工作单元模式.为了正确更新关系,您需要为所有操作使用相同的数据上下文实例.
最简单的方法是使存储库类在创建时接受现有的数据上下文实例,以便它们在共享实例而不是单独的实例上执行其工作.您可以通过沿着以下行向每个存储库添加新构造函数来执行此操作:
public SqlRoleRepository(DataContext context)
{
rolesTable = context.GetTable<Role>();
}
Run Code Online (Sandbox Code Playgroud)
然后,当需要参与相同的工作单元时,使用这些构造函数针对相同的数据上下文实例化您的存储库.
| 归档时间: |
|
| 查看次数: |
1266 次 |
| 最近记录: |