2012-07-16 15 views
7

Ho utilizzato Entity Framework in una soluzione .NET 4.0 per alcune settimane. È EF 4.3.1. Ho creato per primo lo schema del database e generato i miei oggetti entità utilizzando il modello "EF4.x DbContext Generator".Impossibile impostare il campo/proprietà sul tipo di entità con Entity Framework 4.3.1

Avevo tre tabelle nello schema e tutto funzionava perfettamente con i metodi CRUD semplici.

Ora ho aggiunto una quarta tabella, "Soggetti", che ha un riferimento di chiave esterna a una tabella esistente "SourceUri", in modo che un SourceUri possa avere 0-molti soggetti e un Soggetto ha esattamente un SourceUri.

Ho aggiornato il mio modello edmx e sembra corretto. Tuttavia, non importa quello che cerco, non posso non sembrano effettuare le seguenti operazioni:

  • aggiungere un nuovo record SourceUri
  • Aggiungi uno o più soggetti per la nuova SourceUri

Questo è il codice che ho sto attualmente cercando. Puoi vedere che sto salvando il contesto regolarmente, ma in origine stavo salvando le modifiche solo una volta alla fine del metodo.

/// <summary> 
    /// Adds a new Source URI to the system 
    /// </summary> 
    /// <param name="sourceUri">The source URI to add</param> 
    /// <param name="subjectNames">List of subjects for this source URI, in order</param> 
    /// <returns>The added source URI</returns> 
    public SourceUri AddSourceUri(SourceUri sourceUri, IList<string> subjectNames) 
    { 
     try 
     { 
      _logger.Debug("Adding new source URI '{0}', with '{1}' subjects.", sourceUri.Uri, 
       subjectNames != null ? subjectNames.Count : 0); 
      LogSourceUriDetails(sourceUri, "Adding"); 

      using (var dbContext = GetDbContext()) 
      { 
       dbContext.SourceUris.Add(sourceUri); 
       dbContext.SaveChanges(); // this save succeeds 

       // add the subjects if there are any 
       if (subjectNames != null) 
       { 
        for (int i = 0; i < subjectNames.Count; i++) 
        { 
         Subject newSubject = new Subject() 
               { 
                DisplayOrder = i, 
                SourceUriId = sourceUri.SourceUriId, 
                SubjectText = subjectNames.ElementAt(i).Trim() 
               }; 
         _logger.Debug("Adding new subject '{0}' to source URI '{1}'.", newSubject.SubjectText, 
             sourceUri.Uri); 
         dbContext.Subjects.Add(newSubject); // this line fails 
         dbContext.SaveChanges(); 
        } 
       } 

       _logger.Debug("Successfully added new source URI '{0}' with '{1}' subjects. Source URI ID is '{2}'.", 
        sourceUri.Uri, subjectNames != null ? subjectNames.Count : 0, sourceUri.SourceUriId); 
       return sourceUri; 
      } 
     } 
     catch (Exception exception) 
     { 
      _logger.ErrorException(string.Format("An error occurred adding new source URI '{0}' with '{1}' subjects.", 
       sourceUri.Uri, subjectNames != null ? subjectNames.Count : 0), exception); 
      throw; 
     } 
    } 

Il codice aggiunge il nuovo SourceUri e salva le modifiche. Tuttavia, non riesce ad aggiungere il nuovo Soggetto al contesto dati. Non arriva al punto di cercare di salvare quel cambiamento.

L'eccezione è:

Unable to set field/property Subjects on entity type CommentService.DomainObjects.SourceUri. See InnerException for details. 
System.Data.Objects.Internal.PocoPropertyAccessorStrategy.CollectionRemove(RelatedEnd relatedEnd, Object value) 
System.Data.Objects.Internal.EntityWrapper`1.CollectionRemove(RelatedEnd relatedEnd, Object value) 
System.Data.Objects.DataClasses.EntityCollection`1.RemoveFromObjectCache(IEntityWrapper wrappedEntity) 
System.Data.Objects.DataClasses.RelatedEnd.Remove(IEntityWrapper wrappedEntity, Boolean doFixup, Boolean deleteEntity, Boolean deleteOwner, Boolean applyReferentialConstraints, Boolean preserveForeignKey) 
System.Data.Objects.DataClasses.RelatedEnd.FixupOtherEndOfRelationshipForRemove(IEntityWrapper wrappedEntity, Boolean preserveForeignKey) 
System.Data.Objects.DataClasses.RelatedEnd.Remove(IEntityWrapper wrappedEntity, Boolean doFixup, Boolean deleteEntity, Boolean deleteOwner, Boolean applyReferentialConstraints, Boolean preserveForeignKey) 
System.Data.Objects.DataClasses.EntityReference`1.Exclude() 
System.Data.Objects.DataClasses.RelationshipManager.RemoveRelatedEntitiesFromObjectStateManager(IEntityWrapper wrappedEntity) 
System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity) 
System.Data.Entity.Internal.Linq.InternalSet`1.&lt;&gt;c__DisplayClass5.&lt;Add&gt;b__4() 
System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName) 
System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity) 
System.Data.Entity.DbSet`1.Add(TEntity entity) 
CommentService.Business.Managers.SourceUriManager.AddSourceUri(SourceUri sourceUri, IList`1 subjectNames) in C:\Projects\SVN Misc Projects\CommentService\trunk\CommentService.Business\Managers\SourceUriManager.cs:line 152 
CommentService.Web.Comment.AddSourceUri(SourceUri sourceUri, IList`1 subjectNames) in C:\Projects\SVN Misc Projects\CommentService\trunk\CommentService.Web\Comment.svc.cs:line 173 
SyncInvokeAddSourceUri(Object , Object[] , Object[]) 
System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp; outputs) 
System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp; rpc) 
System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet) 

Sono andato in tondo su questo, e ho visto diverse eccezioni leggermente diverse. Sembrano tutti indicare il fatto che la proprietà di navigazione degli oggetti dell'oggetto SourceUri è in qualche modo di sola lettura o di lunghezza fissa (array?).

Le classi di entità generate apparire come segue:

//------------------------------------------------------------------------------ 
// <auto-generated> 
// This code was generated from a template. 
// 
// Manual changes to this file may cause unexpected behavior in your application. 
// Manual changes to this file will be overwritten if the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

namespace CommentService.DomainObjects 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class SourceUri 
    { 
     public SourceUri() 
     { 
      this.Comments = new HashSet<Comment>(); 
      this.Subjects = new HashSet<Subject>(); 
     } 

     public long SourceUriId { get; set; } 
     public string Uri { get; set; } 
     public string Description { get; set; } 
     public System.DateTime DateCreated { get; set; } 
     public string AdminUser { get; set; } 

     public virtual ICollection<Comment> Comments { get; set; } 
     public virtual ICollection<Subject> Subjects { get; set; } 
    } 
} 


//------------------------------------------------------------------------------ 
// <auto-generated> 
// This code was generated from a template. 
// 
// Manual changes to this file may cause unexpected behavior in your application. 
// Manual changes to this file will be overwritten if the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

namespace CommentService.DomainObjects 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class Subject 
    { 
     public Subject() 
     { 
      this.Comments = new HashSet<Comment>(); 
     } 

     public long SubjectId { get; set; } 
     public long SourceUriId { get; set; } 
     public string SubjectText { get; set; } 
     public int DisplayOrder { get; set; } 

     public virtual ICollection<Comment> Comments { get; set; } 
     public virtual SourceUri SourceUri { get; set; } 
    } 
} 

Perché non fa questo lavoro?

breve lista di cose che ho controllato/provato:

  • Lo schema del database è corretto - posso inserire i record come previsto con SQL e primaria chiavi, chiavi esterne e le identità sembrano essere comportarsi correttamente
  • Il modello sembra riflettere correttamente lo schema del database, comprese le identità PK (EntityKey = true, StoreGeneratedPattern = Identity)
  • Sono riuscito a ottenere EF per mantenere i dati nel mio schema, ma dopo che i dati sono stati inseriti, viene generata un'eccezione affermando che il contesto potrebbe non essere sincronizzato, ancora una volta pertinente al non essere in grado per aggiornare la proprietà di navigazione Soggetti dell'oggetto SourceUri
  • Ho provato ad aggiungere gli oggetti alla raccolta dbContext.Subjects e anche alla raccolta SourceUri.Subjects. Ho anche provato a impostare la proprietà SourceUri dell'oggetto invece della proprietà SourceUriId dell'oggetto.
+0

"* Vedere InnerException per i dettagli." * Dice il primo linea nella traccia dello stack. Puoi farlo e aggiungere il messaggio di eccezione interno alla tua domanda? – Slauma

+0

L'eccezione interna è nullo. –

risposta

14

Sono arrivato in fondo a questo problema. Il comportamento problema è stato causato dall'entità SourceUri passata nel metodo tramite un servizio Web WCF.Significava che le proprietà di ICollection dell'oggetto venivano deserializzate come una matrice, che ha una lunghezza fissa e non può essere aggiunta.

ho risolto questo problema modificando il modello che genera i miei soggetti in modo da produrre classi in cui le collezioni sono liste in modo esplicito, come segue:

//------------------------------------------------------------------------------ 
// <auto-generated> 
// This code was generated from a template. 
// 
// Manual changes to this file may cause unexpected behavior in your application. 
// Manual changes to this file will be overwritten if the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

namespace CommentService.DomainObjects 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; // added this 

    public partial class SourceUri 
    { 
     public SourceUri() 
     { 
      this.Comments = new HashSet<Comment>().ToList(); // added this 
      this.Subjects = new HashSet<Subject>().ToList(); // added this 
     } 

     public long SourceUriId { get; set; } 
     public string Uri { get; set; } 
     public string Description { get; set; } 
     public System.DateTime DateCreated { get; set; } 
     public string AdminUser { get; set; } 

     public virtual List<Comment> Comments { get; set; } // altered these to List 
     public virtual List<Subject> Subjects { get; set; } // altered these to List 
    } 
} 
Problemi correlati