无法使用Entity Framework 4.3.1在实体类型上设置字段/属性

时间:2012-07-16 10:55:12

标签: entity-framework entity-framework-4

我已经在.NET 4.0解决方案中使用Entity Framework几周了。它是EF 4.3.1。我首先创建了数据库模式,并使用“EF4.x DbContext Generator”模板生成了我的实体对象。

我在架构中有三个表,并且使用简单的CRUD方法都可以正常工作。

我现在添加了第四个表“Subjects”,它具有对现有表“SourceUri”的外键引用,这样SourceUri可以有0个多个主题,而Subject只有一个SourceUri。

我更新了我的edmx模型,看起来很正确。但是,无论我尝试什么,我似乎无法做到以下几点:

  • 添加新的SourceUri记录
  • 为新的SourceUri添加一个或多个主题

这是我目前正在尝试的代码。您可以看到我定期保存上下文,但最初我只是在方法结束时保存了一次更改。

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

代码添加新的SourceUri并保存更改。但是,它无法将新主题添加到数据上下文中。它没有尝试保存这种变化。

例外是:

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)

我已经四处走动,看到了几个略有不同的异常。它们似乎都指向SourceUri对象的Subjects导航属性在某种程度上是只读或固定长度(数组?)。

生成的实体类如下所示:

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

为什么这不起作用?

我已检查/尝试过的快速列表:

  • 数据库架构看起来是正确的 - 我可以按预期插入记录,使用SQL和主键,外键和身份似乎表现正常
  • 该模型似乎正确反映了数据库架构,包括PK身份(EntityKey = true,StoreGeneratedPattern = Identity)
  • 我设法让EF将数据保存到我的模式中,但是在插入数据之后,会抛出一个异常,指出上下文可能不同步 - 再次与无法更新Subjects导航属性有关。 SourceUri对象
  • 我尝试将Subjects添加到dbContext.Subjects集合,也添加到SourceUri.Subjects集合。我还尝试设置Subject的SourceUri属性而不是Subject的SourceUriId属性。

1 个答案:

答案 0 :(得分:15)

我已经深究这个问题了。问题行为是由SourceUri实体通过WCF Web服务传递给方法引起的。这意味着对象的ICollection属性被反序列化为一个Array,它是固定长度的,无法添加到。

我已经通过更改生成我的实体的模板解决了这个问题,因此它生成了集合明确列出的类,如下所示:

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