EF5 Code First和RIA Services Silverlight "Object reference not set to an instance of an object"错误构建客户端

6
我正在使用RIA服务在Silverlight中使用Entity Framework 5的Code First设置新项目。由于遇到了一些问题,我创建了一个测试项目并将代码贴在下面。
具体来说,每当我尝试构建Silverlight客户端项目以生成客户端代理类时,都会出现“对象引用未设置为对象实例”的错误。
需要明确的是,这个错误不是在运行或调试应用程序时出现的,而是在构建它时出现的。
我已经确定,只有在我的Code First类上定义任何导航属性/外键时才会发生这种情况。
今晚任何帮助都将不胜感激。
    public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime? BirthDate { get; set; }

    public virtual List<Character> Characters { get; set; }
}

public class Character
{
    public int CharacterId { get; set; }
    public int PersonId { get; set; }
    public virtual Person Person { get; set; }
    public string CharacterName { get; set; }
}

public class CharacterDbContext : DbContext
{
    public DbSet<Person> Persons { get; set; }
    public DbSet<Character> Characters { get; set; }

    public CharacterDbContext()
    {
        if (HttpContext.Current == null)
        {
            Database.SetInitializer<CharacterDbContext>(null);
        }
    }
}

[EnableClientAccess]
public class CharacterDbService : DbDomainService<CharacterDbContext>
{
    #region Basic Methods for Person with the context property of Persons

    [Query]
    public IQueryable<Person> GetPersons()
    {
        return DbContext.Persons;
    }

    [Insert]
    public void InsertPerson(Person entity)
    {
        DbEntityEntry<Person> entityEntry = DbContext.Entry(entity);
        if (entityEntry.State != EntityState.Detached)
        {
            entityEntry.State = EntityState.Added;
        }
        else
        {
            DbContext.Persons.Add(entity);
        }
    }

    [Update]
    public void UpdatePerson(Person entity)
    {
        DbContext.Persons.AttachAsModified(entity, ChangeSet.GetOriginal(entity), DbContext);
    }

    [Delete]
    public void DeletePerson(Person entity)
    {
        DbEntityEntry<Person> entityEntry = DbContext.Entry(entity);
        if (entityEntry.State != EntityState.Deleted)
        {
            entityEntry.State = EntityState.Deleted;
        }
        else
        {
            DbContext.Persons.Attach(entity);
            DbContext.Persons.Remove(entity);
        }
    }

    #endregion

    #region Basic Methods for Character with the context property of Characters

    [Query]
    public IQueryable<Character> GetCharacters()
    {
        return DbContext.Characters;
    }

    [Insert]
    public void InsertCharacter(Character entity)
    {
        DbEntityEntry<Character> entityEntry = DbContext.Entry(entity);
        if (entityEntry.State != EntityState.Detached)
        {
            entityEntry.State = EntityState.Added;
        }
        else
        {
            DbContext.Characters.Add(entity);
        }
    }

    [Update]
    public void UpdateCharacter(Character entity)
    {
        DbContext.Characters.AttachAsModified(entity, ChangeSet.GetOriginal(entity), DbContext);
    }

    [Delete]
    public void DeleteCharacter(Character entity)
    {
        DbEntityEntry<Character> entityEntry = DbContext.Entry(entity);
        if (entityEntry.State != EntityState.Deleted)
        {
            entityEntry.State = EntityState.Deleted;
        }
        else
        {
            DbContext.Characters.Attach(entity);
            DbContext.Characters.Remove(entity);
        }
    }

    #endregion
}

是哪个项目出了问题,是Silverlight项目还是EF项目?您能否确认您没有丢失任何文件,并且SL可以在没有WCF RIA Services链接的情况下构建吗? - Rik van den Berg
@Rikkos 这是SL项目,如果我从实体中删除所有关系,它就可以正常构建。请参见下面的部分解决方案。这是使用工具包中的TextTemplate与我已经尝试过的其他解决方案的组合问题。 - KitKat
1个回答

6

您的外键字段没有被映射,因此无法被代理代码生成器(在编译期间调用以构建代理的代码)解释。
您应该在 DbContext 中添加类似以下内容的东西:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
 {
      modelBuilder.Entity<Character>()
          .HasRequired(x=> x.Person)
          .WithMany(x=> x.Characters)
          .HasForeignKey(x=> x.PersonId);
 }

此外,我建议你将
public virtual List<Character> Characters { get; set; }
更改为
public virtual ICollection<Character> Characters { get; set; },因为我不确定代理生成器(以及EF)是否会正确地映射该列表。
编辑:
我认为EF元数据提供程序在描述中没有提供正确的属性。
请在Character.CharacterId和Person.PersonID上放置KeyAttribute,并在Character.Person上添加此行。

[Association("Character_Person", "PersonId", "PersonId", IsForeignKey = true)]

还有一个是关于Person.Characters的

Association("Character_Person", "PersonId", "PersonId")]<br>

编辑:
经过与KitKat的聊天,我们终于找到了问题所在。在代理生成期间,调用Assembly.GetExportedTypes时崩溃,提示需要EF 4.1。 简单地放置

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  <dependentAssembly>
    <assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
  </dependentAssembly>
</assemblyBinding>

在相关的配置文件中做了一些技巧

注意:在此链接中,有一篇我的博客文章更好地解释了如何处理EF5 Code First和WCF Ria Services。


@KitKat 不客气。嗯,我认为你的 EF5 元数据提供程序没有放入必要的 AssociationAttribute。我将编辑我的答案。 - mCasamento
我也尝试过这个。但仍然不行。在对象浏览器中检查微软程序集,我认为最新版本的RIA服务不再支持Code First。我不得不下载第三方Nu Get包才能走到这一步。WCFRIA.EntityFramework - KitKat
我真的很想解决这个问题。虽然现在我会很高兴得到一个关于如何创建ObjectContext而不是DbContext或手动创建代理代码的好教程。有任何相关的指针吗? - KitKat
@KitKat 我实际上正在使用 dbcontext 和 wcf ria 服务。你在使用哪个 CodeGenerator?服务器端是否引用了 Microsoft.ServiceModel.DomainServices.Tools.TextTemplate? - mCasamento
1
@shaahin 好的,我认为这个问题值得我写一篇更详细的博客文章来解释如何处理这些问题。完成后我会在这里放链接。 - mCasamento
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接