所以我真的很难弄清楚什么时候应该附加到一个对象,什么时候不应该附加到一个对象。首先,这是我的(非常简化的)对象模型的小图。
在我的 DAL 中,我每次执行与数据相关的操作时都会创建一个新的 DataContext。比如说,我想保存一个新用户。在我的业务层中,我创建了一个新用户。
var user = new User();
user.FirstName = "Bob";
user.LastName = "Smith";
user.Username = "bob.smith";
user.Password = StringUtilities.EncodePassword("MyPassword123");
user.Organization = someOrganization; // Assume that someOrganization was loaded and it's data context has been garbage collected.
现在我想去保存这个用户。
var userRepository = new RepositoryFactory.GetRepository<UserRepository>();
userRepository.Save(user);
内托!这是我的保存逻辑:
public void Save(User user)
{
if (!DataContext.Users.Contains(user))
{
user.Id = Guid.NewGuid();
user.CreatedDate = DateTime.Now;
user.Disabled = false;
//DataContext.Organizations.Attach(user.Organization);
DataContext.Users.InsertOnSubmit(user);
}
else
{
DataContext.Users.Attach(user);
}
DataContext.SubmitChanges();
// Finished here as well.
user.Detach();
}
所以,我们到了。您会注意到我注释掉了 DataContext 附加到组织的位。如果我加入组织,我会得到以下异常:
NotSupportedException: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.
嗯,那行不通。让我尝试不附加(即注释掉关于附加到组织的那一行)。
DuplicateKeyException: Cannot add an entity with a key that is already in use.
什么?我只能假设这是在尝试插入一个显然是错误的新组织。
那么,伙计们,这是怎么回事?我应该怎么办?什么是正确的方法?看起来 L2S 使这比它应该做的要难得多......
编辑: 我刚刚注意到,如果我尝试查看挂起的更改集 (dataContext.GetChangeSet()),我会得到与之前描述的相同的 NotSupportedException!!什么鬼,L2S?!
最佳答案
它在幕后可能并不完全像这样工作,但这是我对其进行概念化的方式:当您从 DataContext 中调用一个对象时,Linq 所做的其中一件事就是跟踪该对象随时间的变化,以便它知道什么如果您提交更改,则保存回来。如果您丢失了这个原始数据上下文,从中调用的 Linq 对象就没有自从从数据库中调用以来发生的更改的历史记录。
例如:
DbDataContext db = new DbDataContext();
User u = db.Users.Single( u => u.Id == HARD_CODED_GUID );
u.FirstName = "Foo";
db.SubmitChanges();
在这种情况下,由于 User 对象是从数据上下文中调用的,它正在跟踪对“u”的所有更改,并且知道如何将这些更改提交给数据库。
在您的示例中,您有一个 User 对象,该对象已保存在某处(或从其他地方传递并且没有从中调用它的原始 DataContext)。在这种情况下,您必须将其附加到新的数据上下文。
User u; // User object passed in from somewhere else
DbDataContext db = new DbDataContext();
u.FirstName = "Foo";
DbDataContext.Users.Attach( u );
db.SubmitChanges();
由于用户和组织之间的关系在您的数据模型中只是一个 GUID (OrganizationId),因此您只需附加用户对象。
我不确定你的脚手架代码,但可能是这样的:
private const Guid DEFAULT_ORG = new Guid("3cbb9255-1083-4fc4-8449-27975cb478a5");
public void Save(User user)
{
if (!DataContext.Users.Contains(user))
{
user.Id = Guid.NewGuid();
user.CreatedDate = DateTime.Now;
user.Disabled = false;
user.OrganizationId = DEFAULT_ORG; // make the foreign key connection just
// via a GUID, not by assigning an
// Organization object
DataContext.Users.InsertOnSubmit(user);
}
else
{
DataContext.Users.Attach(user);
}
DataContext.SubmitChanges();
}
关于c# - LINQ 到 SQL : To Attach or Not To Attach,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2679698/