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

Entity framework 无法使用实体框架4.3.1在实体类型上设置字段/属性,entity-framework,entity-framework-4,Entity Framework,Entity Framework 4,我已经在.NET4.0解决方案中使用EntityFramework几个星期了。它是EF 4.3.1。我首先创建了数据库模式,并使用“EF4.x DbContext生成器”模板生成了实体对象 我在模式中有三个表,使用简单的CRUD方法都可以正常工作 我现在添加了第四个表“Subjects”,它有一个对现有表“SourceUri”的外键引用,这样一个SourceUri可以有0多个Subjects,而一个Subject正好有一个SourceUri 我已经更新了我的edmx模型,它看起来是正确的。然而,

我已经在.NET4.0解决方案中使用EntityFramework几个星期了。它是EF 4.3.1。我首先创建了数据库模式,并使用“EF4.x DbContext生成器”模板生成了实体对象

我在模式中有三个表,使用简单的CRUD方法都可以正常工作

我现在添加了第四个表“Subjects”,它有一个对现有表“SourceUri”的外键引用,这样一个SourceUri可以有0多个Subjects,而一个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对象的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; }
    }
}
//------------------------------------------------------------------------------
// <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
    }
}
//------------------------------------------------------------------------------
// 
//此代码是从模板生成的。
//
//手动更改此文件可能会导致应用程序出现意外行为。
//如果重新生成代码,将覆盖对此文件的手动更改。
// 
//------------------------------------------------------------------------------
命名空间CommentService.DomainObjects
{
使用制度;
使用System.Collections.Generic;
公共部分类SourceUri
{
publicsourceuri()
{
this.Comments=newhashset();
this.Subjects=newhashset();
}
公共长SourceUriId{get;set;}
公共字符串Uri{get;set;}
公共字符串说明{get;set;}
public System.DateTime DateCreated{get;set;}
公共字符串AdminUser{get;set;}
公共虚拟ICollection注释{get;set;}
公共虚拟ICollection主题{get;set;}
}
}
//------------------------------------------------------------------------------
// 
//此代码是从模板生成的。
//
//手动更改此文件可能会导致应用程序出现意外行为。
//如果重新生成代码,将覆盖对此文件的手动更改。
// 
//------------------------------------------------------------------------------
命名空间CommentService.DomainObjects
{
使用制度;
使用System.Collections.Generic;
公共部分类科目
{
公共主题()
{
this.Comments=newhashset();
}
公共长主体{get;set;}
公共长SourceUriId{get;set;}
公共字符串SubjectText{get;set;}
公共int显示顺序{get;set;}
公共虚拟ICollection注释{get;set;}
公共虚拟源URI源URI{get;set;}
}
}
为什么这样不行

快速列出我检查/尝试过的事项:

  • 数据库模式看起来是正确的-我可以按预期使用SQL和主键插入记录,外键和标识的行为似乎是正确的
  • 模型似乎正确地反映了数据库模式,包括PK标识(EntityKey=true,StoreGeneratedPattern=Identity)
  • 我已经设法让EF将数据持久化到我的模式中,但在插入数据后,会引发一个异常,指出上下文可能不同步,这同样与无法更新SourceUri对象的Subjects导航属性有关
  • 我已经尝试将主题添加到dbContext.Subjects集合,以及SourceUri.Subjects集合。我还尝试设置主题的SourceUri属性,而不是主题的SourceUriId属性

    • 我已经弄清了这个问题的真相。问题行为是由SourceUri实体通过WCF web服务传递到方法中引起的。这意味着对象的ICollection属性被反序列化为一个数组,该数组具有固定长度,无法添加到

      我已通过更改生成实体的模板来解决此问题,以便它生成集合显式列表的类,如下所示:

      //------------------------------------------------------------------------------
      // <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; }
          }
      }
      
      //------------------------------------------------------------------------------
      // <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
          }
      }
      
      //------------------------------------------------------------------------------
      // 
      //此代码是从模板生成的。
      //
      //手动更改此文件可能会导致应用程序出现意外行为。
      //如果重新生成代码,将覆盖对此文件的手动更改。
      // 
      //------------------------------------------------------------------------------
      命名空间CommentService.DomainObjects
      {
      使用制度;
      使用System.Collections.Generic;
      使用System.Linq;//添加了这个
      公共部分类SourceUri
      {
      publicsourceuri()
      {
      this.Comments=new HashSet().ToList();//添加了这个
      this.Subjects=new HashSet().ToList();//添加了这个
      }
      公共长SourceUriId{get;set;}
      公共字符串Uri{get;set;}
      公共字符串说明{get;set;}
      public System.DateTime DateCreated{get;set;}
      公共字符串AdminUser{get;set;}
      公共虚拟列表注释{get;set;}//将其更改为列表
      公共虚拟列表主题{get;set;}//将它们更改为列表
      }
      }
      
      “有关详细信息,请参阅InnerException。”堆栈跟踪中的第一行表示。您可以这样做,并将内部异常消息添加到您的问题中吗?