2012-07-16 33 views
7

Tôi đã sử dụng Khung thực thể trong một giải pháp .NET 4.0 trong một vài tuần. Đó là EF 4.3.1. Trước tiên tôi đã tạo lược đồ cơ sở dữ liệu và tạo đối tượng Entity của mình bằng mẫu "EF4.x DbContext Generator".Không thể đặt trường/thuộc tính trên loại đối tượng bằng Entity Framework 4.3.1

Tôi có ba bảng trong lược đồ và tất cả đều hoạt động tốt với các phương pháp CRUD đơn giản. Bây giờ tôi đã thêm một bảng thứ tư, "Subjects", trong đó có một tham chiếu Key nước ngoài đến một bảng hiện có "SourceUri", như vậy một SourceUri có thể có 0 nhiều đối tượng, và một Subject có chính xác một SourceUri.

Tôi đã cập nhật mô hình edmx của mình và có vẻ chính xác. Tuy nhiên, không có vấn đề gì tôi cố gắng, tôi dường như không thể làm như sau:

  • Thêm một kỷ lục SourceUri mới
  • Thêm một hoặc nhiều đối tượng cho SourceUri mới

Đây là mã tôi hiện đang cố gắng. Bạn có thể thấy tôi đang lưu ngữ cảnh thường xuyên, nhưng ban đầu tôi chỉ lưu các thay đổi một lần ở cuối phương thức.

/// <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; 
     } 
    } 

Mã thêm SourceUri mới và lưu thay đổi. Tuy nhiên, nó không quản lý để thêm đối tượng mới vào bối cảnh dữ liệu. Nó không nhận được như xa như cố gắng để lưu thay đổi đó.

Trường hợp ngoại lệ là:

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) 

Tôi đã đi lang thang trên này, và đã thấy một vài trường hợp ngoại lệ hơi khác nhau. Tất cả chúng dường như chỉ ra một thực tế là thuộc tính navigation của Subjects của đối tượng SourceUri là một cách nào đó theo chiều dài chỉ đọc hoặc cố định (array?).

Các lớp thực thể được tạo ra trông như sau:

//------------------------------------------------------------------------------ 
// <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; } 
    } 
} 

Tại sao không làm việc này?

danh sách nhanh của những điều tôi đã kiểm tra/thử:

  • Giản đồ cơ sở dữ liệu có vẻ đúng - Tôi có thể chèn các bản ghi như mong đợi với SQL và chính phím, phím nước ngoài và bản sắc dường như được hành xử một cách chính xác
  • Mô hình dường như phản ánh chính xác lược đồ cơ sở dữ liệu, bao gồm thông tin nhận dạng PK (EntityKey = true, StoreGeneratedPattern = Identity)
  • Tôi đã quản lý EF để lưu dữ liệu vào lược đồ của mình, nhưng sau khi dữ liệu được chèn vào, nói rằng ngữ cảnh có thể không đồng bộ - một lần nữa liên quan đến việc không thể để cập nhật thuộc tính điều hướng Chủ thể của đối tượng SourceUri
  • Tôi đã thử thêm đối tượng vào bộ sưu tập dbContext.Subjects và cũng vào bộ sưu tập SourceUri.Subjects. Tôi cũng đã thử thiết lập thuộc tính SourceUri của Subject thay vì thuộc tính SourceUriId của Subject.
+0

"* Xem InnerException để biết chi tiết." * Nói là người đầu tiên dòng trong ngăn xếp dấu vết. Bạn có thể làm điều đó và thêm thông điệp ngoại lệ bên trong vào câu hỏi của bạn? – Slauma

+0

Ngoại lệ bên trong là null. –

Trả lời

14

Tôi đã gặp phải vấn đề này. Các hành vi vấn đề đã được gây ra bởi các thực thể SourceUri được thông qua vào phương pháp thông qua một dịch vụ web WCF.Nó có nghĩa là các thuộc tính ICollection của đối tượng đã được deserialized như một mảng, có chiều dài cố định, và không thể được thêm vào.

Tôi đã giải quyết vấn đề này bằng cách thay đổi mẫu mà tạo ra các đối tượng của tôi vì vậy mà nó tạo ra các lớp học nơi các bộ sưu tập là một cách rõ ràng Lists, như sau:

//------------------------------------------------------------------------------ 
// <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 
    } 
} 
Các vấn đề liên quan