LINQ to SQL: Crie um objeto de entidade separada
-
19-09-2019 - |
Pergunta
I têm gerado algumas aulas usando para LINQ to SQL
sendo um deles "Cliente"
Agora eu quero criar um objeto de cliente que está desconectado.
i. Eu posso criar o objeto de mantê-lo em sessão e, em seguida, anexá-lo de volta apenas se eu quiser. Não automaticamente. Por isso só se eu anexá-lo -. Isso deve afetar SubmitChange do meu contexto () caso contrário não
Isso é possível?
Também posso adicionar este objeto destacado para uma coleção de objetos ligados sem afetar SubmitChanges () ou no add será o objeto destacado tornar-se ligado de novo?
Solução
Não há nenhum método "Separar", mas é possível com a serialização:
Customer customerCopy;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, customer);
ms.Position = 0;
customerCopy = (Customer)bf.Deserialize(ms);
}
Esteja ciente de que é pesado para re-anexar o objeto depois. O método de tabela Attach
é mimado -. Você geralmente precisa de uma coluna Version
(tipo timestamp) na entidade a fim de que o trabalho
Nota - Eu só reler a sua pergunta e soa quase como se você simplesmente quer construção o objeto. Se assim for, a construção de um novo Customer
via new Customer()
vai não criar uma entidade ligada. Ele só se apega depois de chamar o método InsertOnSubmit
ou Attach
sobre a mesa.
entidades Além disso, você pode livremente add destacado para uma List<Customer>
(ou similar), contendo entidades ligadas - LINQ to SQL não se preocupa com isso, uma entidade única se apega, se for dispensado pelo próprio ou se você anexá-lo usando DataContext
um dos métodos acima.
Outras dicas
Para LINQ to SQL, apenas o DataContractSerializer é suportado.
Há uma maneira mais performance para separar (), e isso é usando o seguinte método de base:
public void Detach()
{
GetType().GetMethod("Initialize", BindingFlags.Instance |
BindingFlags.NonPublic).Invoke(this, null);
}
Isso irá chamar o método Initialize (), que irá 'Reset' todas as propriedades FK. O truque é que este método só é gerado quando a serialização foi ligado. Há uma maneira de contornar este problema, verifique aqui para mais informações
Vitaliy, Desculpe eu perdi que blogpost. Eu ainda tenho o código embora.
public class EntityBase : IEntityBase
{
/// <summary>
/// Detaches the entity, so it can be added to another dataContext. It does this by setting
/// all the FK properties to null/default.
/// </summary>
public void Detach()
{
// I modified the .tt file to generate the Initialize method by default.
// The call to OnCreated() is moved to the constructor.
GetType().GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, null);
}
}
E aqui está a chamada para Detach () do meu adaptador
public class OrderAdapter : IOrderAdapter
{
public void Add(IOrder order)
{
try
{
using (var db = new ATPDataContext())
{
Order newOrder = (Order)order;
newOrder.Detach(); // not required for insertion, but to keep references to Product
db.Orders.InsertOnSubmit(newOrder);
db.SubmitChanges();
}
}
catch (Exception ex)
{
}
}
}
E no meu arquivo .tt
#region Construction
public <#=class1.Name#>()
{
Initialize();
<# if (class1.HasPrimaryKey) {#>
OnCreated();
<# } #>
}
private void Initialize()
{
<# foreach(Association association in class1.Associations) { #>
<#=association.Storage#> = <#
if (association.IsMany) {
#>new EntitySet<<#=association.Type.Name#>>(attach_<#=association.Member#>, detach_<#=association.Member#>);
<# } else {
#>default(EntityRef<<#=association.Type.Name#>>);
<# }
}
#>
}
#endregion
HTH!