LINQ to SQL: Créer un objet entité détachée
-
19-09-2019 - |
Question
J'ai généré quelques classes à l'aide de LINQ to SQL
l'un d'entre eux étant "Client"
Maintenant, je veux créer un objet client qui est déconnecté.
i.e.. Je peux créer l'objet le garder en session, puis le joindre de nouveau que si je veux. Pas automatiquement. Par conséquent que si je le joindre -. Il devrait avoir une incidence sur SubmitChange mon contexte () sinon pas
Est-ce possible?
puis-je ajouter aussi cet objet détaché à une collection d'objets attachés sans affecter SubmitChanges () ou ajouter l'objet sera détaché à nouveau s'attacher?
La solution
Il n'y a pas la méthode « Détacher », mais il est possible avec sérialisation:
Customer customerCopy;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, customer);
ms.Position = 0;
customerCopy = (Customer)bf.Deserialize(ms);
}
Sachez qu'il est lourd à rattacher l'objet par la suite. La méthode de la table de Attach
est tatillon -. Il faut généralement une colonne Version
(type d'horodatage) sur l'entité pour que cela fonctionne
Note - Je viens de relire votre question et il semble presque comme si vous voulez simplement construire l'objet. Dans ce cas, la construction d'une nouvelle Customer
via new Customer()
sera pas créer une entité rattachée. Il ne devient attaché une fois que vous invoquez la méthode InsertOnSubmit
ou Attach
sur la table.
En outre, vous pouvez librement ajouter des entités détachés à un List<Customer>
(ou similaire) contenant des entités rattachées - LINQ to SQL ne se soucie pas de cela, une entité ne devient attachée si elle est distribuée par le DataContext
lui-même ou si vous attachez à l'aide l'un des procédés ci-dessus.
Autres conseils
Pour LINQ to SQL, seul le DataContractSerializer est pris en charge.
Il y a une façon plus performante à Détachez (), et c'est la méthode de base suivante:
public void Detach()
{
GetType().GetMethod("Initialize", BindingFlags.Instance |
BindingFlags.NonPublic).Invoke(this, null);
}
appellera la méthode initialize () qui « reset » toutes les propriétés FK. L'astuce est que cette méthode est uniquement générée lorsque sérialisation a été activée. Il y a un moyen de contourner ce problème, vérifiez pour plus d'infos
Vitaliy, Désolé j'ai perdu que blogpost. Je n'ai toujours le code bien.
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);
}
}
Et voici l'appel à Détachez () de mon adaptateur
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)
{
}
}
}
Et dans mon dossier .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!