Perceber:
1. As "entidades" mencionadas neste artigo são todas geradas por LINQ TO SQL (ou seja, .dbml)
2. Você precisa entender como LINQ TO SQL implementa associações de tabelas, EntitySet e EntityRef
Talvez depois de ver o título você pense que a questão é relativamente abstrata, então deixe-me dar um exemplo para explicar o problema em detalhes.
Na arquitetura de N camadas baseada em LINQ TO SQL, se precisarmos atualizar uma entidade, o processo deverá ser o seguinte:
processo
BLL.GetModel (p => p.id == 1) -> Modifique o valor do atributo (campo) correspondente -> BLL.Update (entidade entidade) -> DAL.Update (entidade entidade) -> Atualização bem-sucedida
Neste momento, precisamos passar esta entidade da camada de negócios (BLL) para a camada de acesso a dados (DAL). Quando o método GetModel retornar a entidade, o DataContext será liberado imediatamente e, em seguida, reinstalado quando o DAL. O método Update (entidade entidade) é executado. Crie um DataContext para realizar a operação de atualização; pode-se observar que a entidade passada é passada do primeiro DataContext para outro DataContext. Ao operar em diferentes DataContexts no LINQ TO SQL, são necessárias operações adicionais. ser executado primeiro, ou seja, context.Entity. Attach(entity,true); Finalmente context.SubmitChanges();
Vamos dar uma olhada no código:
código
classe BLL
{
DAL somente leitura privado dal = new DAL();
public LinqToSqlProvider.User GetModel(Expressão<Func<LinqToSqlProvider.User, bool>> expressão)
{
dal.GetModel(expressão);
}
atualização pública void (entidade LinqToSqlProvider.User)
{
dal.Update(entidade);
}
}
classe DAL
{
public LinqToSqlProvider.User GetModel(Expressão<Func<LinqToSqlProvider.User, bool>> expressão)
{
Entrada LinqToSqlProvider.User = novo CriTextBroadcast.LinqToSqlProvider.User();
usando (contexto CriTextBroadcastDBDataContext = DataContext)
{
entrada = context.User.SingleOrDefault(expressão);
}
entrada de retorno;
}
atualização pública void (entidade LinqToSqlProvider.User)
{
usando (contexto CriTextBroadcastDBDataContext = DataContext)
{
context.User.Attach(entrada, verdadeiro);
context.SubmitChanges();
}
}
}
Na verdade, quando usarmos o código acima para operar, ocorrerá esta exceção:
Tentativa de anexar ou adicionar entidade, esta entidade não é uma nova entidade, pode ser carregada de outro DataContext...
Depois de verificar muitas informações sem sucesso, finalmente vi uma pergunta semelhante em um posto estrangeiro. Acontece que a tabela correspondente a esta entidade possui diversas tabelas relacionadas, como: Usuário -> Mensagem, Usuário -> Imagens, etc.
Atributos como EntitySet<Message> Message serão gerados automaticamente ao gerar classes de entidade. Como não lemos esses conteúdos associados juntos ao obter a entidade, ocorrerá uma ObjectDisposedException nesses atributos ao anexar (Attach). usado para consultar esta entidade foi liberado.
Solução:
código
/// <resumo>
/// A entidade auxiliar LinqToSql é separada do DataContext original
/// </sumário>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entity"></param>
public static void Detatch<TEntity>(entidade TEntity)
{
Digite t = entidade.GetType();
Propriedades System.Reflection.PropertyInfo[] = t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
foreach (var propriedade em propriedades)
{
string nome = propriedade.Nome;
if (property.PropertyType.IsGenericType &&
property.PropertyType.GetGenericTypeDefinition() == typeof(EntitySet<>))
{
propriedade.SetValue (entidade, nulo, nulo);
}
}
System.Reflection.FieldInfo[] campos = t.GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
foreach (var campo em campos)
{
string nome = campo.Nome;
if (campo.FieldType.IsGenericType &&
field.FieldType.GetGenericTypeDefinition() == typeof(EntityRef<>))
{
field.SetValue(entidade,nulo);
}
}
System.Reflection.EventInfo eventPropertyChanged = t.GetEvent("PropertyChanged");
System.Reflection.EventInfo eventPropertyChanging = t.GetEvent("PropertyChanging");
if (eventPropertyChanged! = nulo)
{
eventPropertyChanged.RemoveEventHandler (entidade, nulo);
}
if (eventPropertyChanging! = nulo)
{
eventPropertyChanging.RemoveEventHandler (entidade, nulo);
}
}
Após obter a entidade, você deve usar o método Detach(entity) para separar a entidade do DataContext original e, em seguida, anexá-la ao novo DataContext.