Delete Action in asp.net MVC using DB context - c#

I have a problem with my delete action, I'm getting this exception :
A first chance exception of type
'System.Data.Entity.Infrastructure.DbUpdateException' occurred in
EntityFramework.dll
Additional information: Entities in 'Model1Container.PublicationSet'
participate in the 'PublicationQuartier' relationship. 0 related
'Quartier' were found. 1 'Quartier' is expected.
Here my Delete Action :
[HttpPost]
public ActionResult DeleteOffreLocation(int id, OffreLocation offreLocation)
{
try
{
db.Entry(offreLocation).State = System.Data.Entity.EntityState.Deleted;
db.SaveChanges();
return RedirectToAction("ListOffreLocation");
}
catch
{
return View();
}
}
"OffreLocation" Model :
public partial class OffreLocation : Publication
{
public OffreLocation()
{
this.Locataire = new HashSet<Locataire>();
this.DemandeLocation = new HashSet<DemandeLocation>();
this.DemandeLocation1 = new HashSet<DemandeLocation>();
this.DemandeLocation2 = new HashSet<DemandeLocation>();
this.DemandeLocation3 = new HashSet<DemandeLocation>();
}
public string OffreLocation_TypeLog { get; set; }
public string OffreLocation_Sante { get; set; }
public double OffreLocation_Loyer { get; set; }
public System.DateTime OffreLocation_DateDisponibilite { get; set; }
public double OffreLocation_Superficie { get; set; }
public short OffreLocation_NbreChambre { get; set; }
public short OffreLocation_NbrePieces { get; set; }
public virtual ICollection<Locataire> Locataire { get; set; }
public virtual Proprietaire Proprietaire { get; set; }
public virtual ICollection<DemandeLocation> DemandeLocation { get; set; }
public virtual ICollection<DemandeLocation> DemandeLocation1 { get; set; }
public virtual ICollection<DemandeLocation> DemandeLocation2 { get; set; }
public virtual ICollection<DemandeLocation> DemandeLocation3 { get; set; }
}
"Publication" Model:
public partial class Publication
{
public Publication()
{
this.Photo = new HashSet<Photo>();
}
public int Publication_ID { get; set; }
public string Publication_Statut { get; set; }
public bool Publication_Meublee { get; set; }
public string Publication_Descriptif { get; set; }
public bool Publication_ContactParAgence { get; set; }
public double Publication_Maps_Latitude { get; set; }
public double Publication_Maps_Longitude { get; set; }
public virtual Quartier Quartier { get; set; }
public virtual ICollection<Photo> Photo { get; set; }
}
and finaly here my DB Container:
public partial class Model1Container : DbContext
{
public Model1Container()
: base("name=Model1Container")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Utilisateur> UtilisateurSet { get; set; }
public DbSet<Abonnement> AbonnementSet { get; set; }
public DbSet<AbonnementHistorique> AbonnementHistoriqueSet { get; set; }
public DbSet<ColocataireIdeal> ColocataireIdealSet { get; set; }
public DbSet<Publication> PublicationSet { get; set; }
public DbSet<Quartier> QuartierSet { get; set; }
public DbSet<Ville> VilleSet { get; set; }
public DbSet<RegionProvince> RegionProvinceSet { get; set; }
public DbSet<Photo> PhotoSet { get; set; }
public DbSet<MessageLocation> MessageLocationSet { get; set; }
public DbSet<MessageColocation> MessageColocationSet { get; set; }
public System.Data.Entity.DbSet<COM.MENNILIK.Models.Locataire> Locataires { get; set; }
public System.Data.Entity.DbSet<COM.MENNILIK.Models.OffreLocation> OffreLocations { get; set; }
}

Actually you need to remove the object passed to the view. You can either use id or your model OffreLocation. I will give you an example with id.
[HttpPost]
public ActionResult DeleteOffreLocation(int id, OffreLocation offreLocation)
{
try
{
var offreLocationGetById =db.OffreLocations.Find(id);
if(offreLocationGetById!=null)
db.OffreLocations.Remove(offreLocationGetById);
db.SaveChanges();
return RedirectToAction("ListOffreLocation");
}
catch
{
return View();
}
}
I will suggest also you comment your OnModelCreating as you are not using FluentApi code and beside you throw an Exception. It is a suggestion.

it seems to be a model validation error. I'm quite sure that Quartier is required and in the offreLocation from your Action, Quartier should be null.
so you have to :
populate Quartier, or
disable validation.

Related

Automapper missing type map configuration

I can't seem to figure out what is going wrong here, I have configured AutoMapper as follows
services.AddAutoMapper(typeof(MetingenView), typeof(Meting));
And in the controller like this:
public MetingenController(IMapper mapper)
{
this._mapper = mapper;
}
After, I use it like this:
var entity = await this.Context.MetingenView.AsNoTracking().FirstOrDefaultAsync(g =>g.IdMeting == key);
if (entity == null)
{
return NotFound();
}
data.Patch(entity);
var meting = await this.Context.Meting.FirstOrDefaultAsync(m => m.IdMeting == key);
this._mapper.Map(entity, meting);
Then the error rolls out:
AutoMapper.AutoMapperMappingException: Missing type map configuration
or unsupported mapping.
EDIT:
Here are the Meting, and MetingenView classes:
public partial class Meting
{
public int IdMeting { get; set; }
public int IdKoeling { get; set; }
public int IdWerknemer { get; set; }
public int IdGebouw { get; set; }
public int Temperatuur { get; set; }
public DateTime AfgenomenTijd { get; set; }
public string ProductNaam { get; set; }
public string Actie { get; set; }
public DateTime? DatumOntstaan { get; set; }
public DateTime? DatumMutatie { get; set; }
public int IndVerwijderd { get; set; }
public DateTime? DatumVerwijderd { get; set; }
public virtual Gebouw IdGebouwNavigation { get; set; }
public virtual Koeling IdKoelingNavigation { get; set; }
public virtual Werknemer IdWerknemerNavigation { get; set; }
}
public partial class MetingenView
{
[Key]
public int IdKlant { get; set; }
public string Locatie { get; set; }
public string SoortKoeling { get; set; }
public int IdMeting { get; set; }
public int IdKoeling { get; set; }
public int IdWerknemer { get; set; }
public int IdGebouw { get; set; }
public int Temperatuur { get; set; }
public string Actie { get; set; }
public string ProductNaam { get; set; }
public DateTime AfgenomenTijd { get; set; }
}
I think the mapping between Meting and MetingenView is not configured in AutoMapper. If you use Asp.Net Core, you could create a profile.
public class MetingProfile : Profile
{
public MetingProfile()
{
CreateMap<MetingenView, Meting>();
}
}
This would create a default mapping that two types have the same property. If you want to config property mapping manually, Function ForMember() would be used.
For example, if you wish that the property MetingenView.IdGebouw maps Meting.IndVerwijderd, you can code this:
CreateMap<MetingenView, Meting>()
.ForMember(dest=>dest.IdGebouw, opt=>opt.MapFrom(src=>src.IndVerwijderd));

asp.Net How to save data to junction table in controller

How can I save data to junction table from controller?
public ActionResult Create(KreatorZamowienNabywca model)
{
db.KreatoryZamowien.Add(model.KreatorZamowien);
db.Nabywcy.Add(model.Nabywca);
db.SaveChanges();
}
My database schema:
KreatorZamowien(Id, NumerZamowienia) -------------------------------|
|
NabywcaKreatorzamowien (KreatorZamowien_Id, Nabywca_Nabywca_Id)------|
|
Nabywca(Nabywca_Id, Nazwa) ------------------------------------------|
KreatorZamowien.cs
public class KreatorZamowien
{
public int Id { get; set; }
public int NumerZamowienia { get; set; }
public virtual ICollection<Nabywca> Nabywcy { get; set; }
}
Nabywca.cs
public class Nabywca
{
public int NabywcaId { get; set; }
public string Nazwa { get; set; }
public virtual ICollection<KreatorZamowien> KreatoryZamowien { get; set; }
}
Model containing 2 models to display them in View:
KreatoryZamowienNabywca.cs
public class KreatorZamowienNabywca
{
public KreatorZamowien KreatorZamowien { get; set; }
public Nabywca Nabywca { get; set; }
}
Just cross reference both objects.
public class KreatorZamowien
{
public int Id { get; set; }
public int NumerZamowienia { get; set; }
public virtual ICollection<Nabywca> Nabywcy { get; set; } = new Hashset<Nabywca>();
}
public class Nabywca
{
public int NabywcaId { get; set; }
public string Nazwa { get; set; }
public virtual ICollection<KreatorZamowien> KreatoryZamowien { get; set; } = new Hashset<KreatorZamowien>();
}
public ActionResult Create(KreatorZamowienNabywca model)
{
model.KreatorZamowien.Nabywcy.Add(model.Nabywca);
model.Nabywca.KreatoryZamowien.Add(model.KreatorZamowien);
db.KreatoryZamowien.Add(model.KreatorZamowien);
db.Nabywcy.Add(model.Nabywca);
db.SaveChanges();
}

Dbcontext creating columns that I never made

I'm trying to create a view, which previously got an ID, which is working fine(checked in debugger, ID is correct), to invoke a method:
public ActionResult DetaljiNarudzbe(int id)
{
DetaljiNarudzbeViewModel model = new DetaljiNarudzbeViewModel();
model.Narudzba = ctx.Naruzbee.Where(x => x.Id == id).First();
model.StatusNarudzbe = ctx.StatusiNarudzbi.Where(x => x.Id == model.Narudzba.StatusNarudzbeId).FirstOrDefault();
model.Primaoc = ctx.Primaoci.Where(x => x.Id == model.Narudzba.PrimaocId).FirstOrDefault();
model.Adresa = ctx.Adrese.Where(x => x.Id == model.Narudzba.AdresaId).FirstOrDefault();
model.Grad = ctx.Gradovi.Where(x => x.Id == model.Adresa.GradId).FirstOrDefault();
model.StavkeNarudzbe = ctx.StavkeNarudzbi.Where(x => x.Narudzbe_Id == id).ToList();
model.Klijent = ctx.Klijenti.Where(x => x.Id == model.Narudzba.KlijentId).FirstOrDefault();
model.Korisnik = ctx.Korisnici.Where(x => x.Id == model.Klijent.KorisnikId).FirstOrDefault();
return View("DetaljiNarudzbe", model);
}
However, it keeps crashing at this part
model.StavkeNarudzbe = ctx.StavkeNarudzbi.Where(x => x.Narudzbe_Id == id).ToList();
It throws an exception, because for some reason, I think the context created another column called Narudzbe_Id1, which can't be null.
https://imgur.com/a/UFxXB - Image of the given exception
Further proof that it's an issue with dbcontext:
https://imgur.com/a/KEOe3
The extra column doesn't appear in the database on the SQL server's side, where I'm getting the data from.
If it helps, I'm posting the other relevant classes below:
public class StavkaNarudzbe : IEntity
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
public string Naziv { get; set; }
public int Tezina { get; set; }
public double Cijena { get; set; }
public int Narudzbe_Id { get; set; }
public virtual Narudzbe Narudzbe { get; set; }
}
public class MojKontekst : DbContext
{
public MojKontekst() : base("DostavaConnString")
{
}
public DbSet<Adresa> Adrese { get; set; }
public DbSet<Grad> Gradovi { get; set; }
public DbSet<DetaljiVozila> DetaljiVozilaa { get; set; }
public DbSet<Klijent> Klijenti { get; set; }
public DbSet<Korisnik> Korisnici { get; set; }
public DbSet<Kurir> Kuriri { get; set; }
public DbSet<Kvar> Kvarovi { get; set; }
public DbSet<Obavijest> Obavijesti { get; set; }
public DbSet<Narudzbe> Naruzbee { get; set; }
public DbSet<Posiljka> Posiljke { get; set; }
public DbSet<Prelazi> Prelazii { get; set; }
public DbSet<Primaoc> Primaoci { get; set; }
public DbSet<Skladiste> Skladista { get; set; }
public DbSet<StatusNarudzbe> StatusiNarudzbi { get; set; }
public DbSet<StavkaNarudzbe> StavkeNarudzbi { get; set; }
public DbSet<Vozilo> Vozila { get; set; }
public DbSet<VrstaVozila> VrsteVozila { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
public class DetaljiNarudzbeViewModel
{
public Klijent Klijent;
public Korisnik Korisnik;
public Narudzbe Narudzba;
public List<StavkaNarudzbe> StavkeNarudzbe;
public StatusNarudzbe StatusNarudzbe;
public Primaoc Primaoc;
public Adresa Adresa;
public Grad Grad;
}
public class Narudzbe : IEntity
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
public string SifraNarudzbe { get; set; }
public DateTime DatumNarudzbe { get; set; }
public bool Osigurano { get; set; }
public bool BrzaDostava { get; set; }
public int BrojPaketa { get; set; }
public int KlijentId { get; set; }
public virtual Klijent Klijent { get; set; }
public int AdresaId { get; set; }
public virtual Adresa Adresa { get; set; }
public Nullable<int> PosiljkaId { get; set; }
public virtual Posiljka Posiljka { get; set; }
public int StatusNarudzbeId { get; set; }
public virtual StatusNarudzbe StatusNarudzbe{ get; set; }
public int PrimaocId { get; set; }
public virtual Primaoc Primaoc { get; set; }
public Nullable<System.DateTime> VrijemeIsporuke { get; set; }
public int CijenaNarudzbe { get; set; }
}
Exception Text: Invalid column name Narudzbe_Id1
This is Entity Framework trying to follow it's standard naming conventions for relationship columns.
See: https://msdn.microsoft.com/en-us/library/jj819164(v=vs.113).aspx for more information this.
As you are using non-standard names for your foreign key columns (i.e. Narudzbe_Id should be NarudzbeId) you'll need to let EF know how to link up your models. Either rename the properties of your classes to follow this naming convention, or use Data Annotations to explicitly tell EF about your relationships.
For example, try adding a ForeignKey attribute (found in the System.Componentmodel.Dataannotations.Schema namespace) like so:
public class StavkaNarudzbe : IEntity
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
public string Naziv { get; set; }
public int Tezina { get; set; }
public double Cijena { get; set; }
public int Narudzbe_Id { get; set; }
[ForeignKey("Narudzbe_Id")]
public virtual Narudzbe Narudzbe { get; set; }
}

JSON circular reference in asp mvc 5

I am getting an a Circular Reference Serialization Error and failed to load result...status of 500.
I'm trying to create a dynamic dropdown list with the options from the database, appending options with js.
those are my class:
public class IdentificacionViewModel
{ public virtual Causas Causas { get; set; }
public virtual Identificacion Idententificacion { get; set; }
}
public partial class Causas
{
public int Id { get; set; }
public string Causa { get; set; }
public string Agente { get; set; }
public Nullable<int> Id_Subproceso { get; set; }
public Nullable<int> Id_identificacion { get; set; }
public virtual Identificacion Identificacion { get; set; }
public virtual Subprocesos Subprocesos { get; set; }
}
public Identificacion()
{
this.Causas = new HashSet<Causas>();
}
public int Id { get; set; }
public string Nombre { get; set; }
public Nullable<int> Id_Servicio { get; set; }
public string Etapa { get; set; }
public string Riesgo { get; set; }
public string EfectoProb { get; set; }
public virtual ICollection<Causas> Causas { get; set; }
public virtual Servicios Servicios { get; set; }
public virtual Impacto Impacto { get; set; }
}
my controller is:
public ActionResult GetA()
{
var category = db.Causas.ToList();
return Json(category, JsonRequestBehavior.AllowGet);
}
i don't know what could be the problem and thanks for the help.
Lazy Loading of the Causas collection can be turned off by making the Causas property non-virtual
public ICollection<Causas> Causas { get; set; }
Loading of the Causas collection can still be achieved using eager loading
var Identification = context.Identificacion
.Include(b => b.Causas)
.ToList();

Why is my EF detaching not enough?

I try to detach an entity of type group.
Actucally I save it in my cache, and detach it a moment before responding the client.
On the next request I get the group from the cache and re-attch a new objectContext.
However I get An entity object cannot be referenced by multiple instances of IEntityChangeTracker
I know attach includes all related entities but detach doesn't. There I have to detach every related entity.
What am I missing in my detach?
here is my entities hirarchy:
public partial class App
{
public App()
{
this.Pairs = new HashSet<Pair>();
}
public string AppName { get; set; }
public System.Guid AppGuid { get; set; }
public string ClientAppID { get; set; }
public bool IsDeleted { get; set; }
public Nullable<System.DateTime> CreatedDate { get; set; }
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual AppsData AppsData { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}
public partial class AppsData
{
public System.Guid AppGuid { get; set; }
public string Url { get; set; }
public string DisplayName { get; set; }
public string AppDesc { get; set; }
public string PrivacyPolicyUrl { get; set; }
public string TermsOfUseUrl { get; set; }
public string LocalizationKey { get; set; }
public string Compatibility { get; set; }
public bool HiddenApp { get; set; }
public bool IsExperimental { get; set; }
public virtual App App { get; set; }
}
public partial class Browser
{
public Browser()
{
this.BrowserVersions = new HashSet<BrowserVersion>();
}
public int BrowserID { get; set; }
public string BrowserName { get; set; }
public string BrowserCode { get; set; }
public virtual ICollection<BrowserVersion> BrowserVersions { get; set; }
}
public partial class BrowserVersion
{
public BrowserVersion()
{
this.BrowserVerToCriterias = new HashSet<BrowserVerToCriteria>();
}
public System.Guid BrowserVersionID { get; set; }
public int BrowserID { get; set; }
public string Version { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public Nullable<int> Group_Id { get; set; }
public virtual Browser Browser { get; set; }
public virtual ICollection<BrowserVerToCriteria> BrowserVerToCriterias { get; set; }
}
public partial class BrowserVerToCriteria
{
public System.Guid CriteriaID { get; set; }
public System.Guid BrowserVersionID { get; set; }
public string ConditionBrowserVersion { get; set; }
public virtual BrowserVersion BrowserVersion { get; set; }
public virtual Criterion Criterion { get; set; }
}
public partial class CommonConfig
{
public int ID { get; set; }
public string NAME { get; set; }
public string VALUE { get; set; }
public System.DateTime CREATED_DATE { get; set; }
public System.DateTime UPDATED_DATE { get; set; }
public byte GROUP_ID { get; set; }
public string DESCRIPTION { get; set; }
}
public partial class Country
{
public Country()
{
this.Criteria = new HashSet<Criterion>();
this.Criteria1 = new HashSet<Criterion>();
}
public int CountryID { get; set; }
public string CountryCode { get; set; }
public string CountryName { get; set; }
public virtual ICollection<Criterion> Criteria { get; set; }
public virtual ICollection<Criterion> Criteria1 { get; set; }
}
public Criterion()
{
this.BrowserVerToCriterias = new HashSet<BrowserVerToCriteria>();
this.Countries = new HashSet<Country>();
this.CountriesExceptions = new HashSet<Country>();
this.Pairs = new HashSet<Pair>();
}
public System.Guid CriteriaID { get; set; }
public string Domains { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public string DomainsExclude { get; set; }
public virtual ICollection<BrowserVerToCriteria> BrowserVerToCriterias { get; set; }
public virtual ICollection<Country> Countries { get; set; }
public virtual ICollection<Country> CountriesExceptions { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}
public partial class CTID
{
public string CTID1 { get; set; }
public string AppVersion { get; set; }
}
public partial class CtidPgPastExistence
{
public string Ctid { get; set; }
}
public partial class Group
{
public Group()
{
this.Pairs = new HashSet<Pair>();
}
public System.Guid GroupId { get; set; }
public int TestId { get; set; }
public int IdInTest { get; set; }
public bool WelcomeExperienceEnabledByDefault { get; set; }
public virtual MamConfiguration MamConfiguration { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}
public partial class MamConfiguration
{
public MamConfiguration()
{
this.Groups = new HashSet<Group>();
this.MamConfigurationCTIDs = new HashSet<MamConfigurationCTID>();
}
public int TestID { get; set; }
public string TestName { get; set; }
public string Description { get; set; }
public int StatusId { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public bool IsProd { get; set; }
public int TestTraffic { get; set; }
public virtual ICollection<Group> Groups { get; set; }
public virtual MamConfigurationStatus MamConfigurationStatus { get; set; }
public virtual ICollection<MamConfigurationCTID> MamConfigurationCTIDs { get; set; }
}
public partial class MamConfigurationCTID
{
public int TestID { get; set; }
public string CTID { get; set; }
public virtual MamConfiguration MamConfiguration { get; set; }
}
public partial class MamConfigurationStatus
{
public MamConfigurationStatus()
{
this.MamConfigurations = new HashSet<MamConfiguration>();
}
public int StatusId { get; set; }
public string Status { get; set; }
public virtual ICollection<MamConfiguration> MamConfigurations { get; set; }
}
public partial class Pair
{
public Pair()
{
this.Groups = new HashSet<Group>();
}
public System.Guid PairID { get; set; }
public System.Guid CriteriaID { get; set; }
public System.Guid AppGuid { get; set; }
public virtual App App { get; set; }
public virtual Criterion Criterion { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
public partial class SettingsServicesConfig
{
public int ID { get; set; }
public string Name { get; set; }
public string URL { get; set; }
public int Interval { get; set; }
public System.DateTime UPDATED_DATE { get; set; }
public System.DateTime CREATED_DATE { get; set; }
public int GROUP_ID { get; set; }
}
here is my detach function:
public void Detach<T>(MaMDBEntities maMdbEntities, T item) where T : class, new()
{
switch (typeof (T).Name.ToLower())
{
case "group":
{
var group = item as Group;
if (group == null)
{
mApplicationLogger.Error(string.Format("Couldn't cast item to type 'Group'"));
throw new InvalidCastException(string.Format("Couldn't cast item to type 'Group'"));
}
DetachState(maMdbEntities, group.MamConfiguration);
foreach (var pair in group.Pairs.ToList())
{
DetachState(maMdbEntities, pair.App);
DetachState(maMdbEntities, pair.App.AppsData);
foreach (var country in pair.Criterion.Countries.ToList())
{
DetachState(maMdbEntities, country);
}
foreach (var country in pair.Criterion.CountriesExceptions.ToList())
{
DetachState(maMdbEntities, country);
}
foreach (var browserVerToCriterias in pair.Criterion.BrowserVerToCriterias.ToList())
{
DetachState(maMdbEntities, browserVerToCriterias.BrowserVersion.Browser);
DetachState(maMdbEntities, browserVerToCriterias.BrowserVersion);
DetachState(maMdbEntities, browserVerToCriterias);
}
DetachState(maMdbEntities, pair.Criterion);
DetachState(maMdbEntities, pair);
}
break;
}
}
maMdbEntities.Entry(item).State = EntityState.Detached;
}
private static void DetachState(MaMDBEntities maMdbEntities, object item)
{
maMdbEntities.Entry(item).State = EntityState.Detached;
}
I believe that you need to make sure that none of the entities which remain in your context, reference any of those which have been detached. So if say, something else references a detached instance of Pair, the context will quite happily find it, traverse its navigation properties and add the whole lot back in.
Rather than setting the State property have you tried:
((IObjectContextAdapter)maMdbEntities).ObjectContext.Detach(item);
This is supposed to detach any links to the item being detached in addition to the item itself.
EDIT
Ok, lets look at the "detach any links to the item being detached ...", ObjectContext.Detach ultimately calls this method:
// System.Data.Objects.EntityEntry
internal void Detach()
{
base.ValidateState();
bool flag = false;
RelationshipManager relationshipManager = this._wrappedEntity.RelationshipManager;
flag = (base.State != EntityState.Added && this.IsOneEndOfSomeRelationship());
this._cache.TransactionManager.BeginDetaching();
try
{
relationshipManager.DetachEntityFromRelationships(base.State);
}
finally
{
this._cache.TransactionManager.EndDetaching();
}
this.DetachRelationshipsEntries(relationshipManager);
IEntityWrapper wrappedEntity = this._wrappedEntity;
EntityKey entityKey = this._entityKey;
EntityState state = base.State;
if (flag)
{
this.DegradeEntry();
}
else
{
this._wrappedEntity.ObjectStateEntry = null;
this._cache.ChangeState(this, base.State, EntityState.Detached);
}
if (state != EntityState.Added)
{
wrappedEntity.EntityKey = entityKey;
}
}
DetachEntityFromRelationships breaking down all the links.
The documentation on ObjectContext.Detach is not specific about the tearing down of links http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.detach.aspx it does say "After the Detach method is called, the system will no longer keep references that point to this object and it can be collected by the garbage collector", which implies all LinkDescriptors will also have been removed.
With regards your 3rd comment "Do you think IObjectContextAdapter will enable full detachment. Or there will always be other object in context that I will misss and not detach?" there are two things here; there is the property of the object and the LinkDescriptor which the context uses to track to the relationship. Detach merely stops tracking an object's relationships by detaching the LinkDescriptors, it doesn't detach the object at the other end of the relationship. Neither does it set such properties to null, if you inspect the object after detaching it will still have those properties set.
Is this the best approach? Detaching and reattaching is difficult to get right. If you need to detach and reattach I would suggest you move your deep detach rountines into the classes themselves rather than in a generic method.
That said, you wrote "On the next request I get the group from the cache..." which leads to me wonder what would be the longest period of time between two requests? Could you be introducing concurrency issues by caching? Are you hosting your WCF service in IIS? Could you use IIS's caching if concurrency will not be a problem? Are you handling all requests on the same thread? You might not be aware that ObjectContext instance methods are not thread safe.

Categories

Resources