.net - Entity Framework 代码第一个自加入, 'Multiplicity is not valid in Role'

标签 .net entity-framework code-first .net-4.5

我被这个错误困住了,找不到解决方案。我已经尝试了几件事,但无法想出解决方案。

这是我的问题:

代码:

namespace ProjectTracker.Database.Entities
{
    [DataContract]
    public class User
    {
        [DataMember]
        public int Id { get; set; }

        [Required]
        [MaxLength(50)]
        [DataMember]
        public string UserName { get; set; }

        [Required]
        [MaxLength(100)]
        [DataType(DataType.Password)]
        [DataMember]
        public string Password { get; set; }

        [DataMember]
        public bool IsPasswordExpired { get; set; }

        [Required]
        [DataMember]
        public DateTime CreatedDate { get; set; }

        [Required]
        [ForeignKey("CreatedBy")]
        [DataMember]
        public int CreatedByUserId { get; set; }

        [DataMember]
        public virtual User CreatedBy { get; set; }

        [Required]
        [DataMember]
        public DateTime LastUpdatedDate { get; set; }

        [ForeignKey("LastUpdatedBy")]
        [DataMember]
        public int? LastUpdatedByUserId { get; set; }

        [DataMember]
        public virtual User LastUpdatedBy { get; set; }
    }
}

以下是我从 Web 服务调用它时获得的异常详细信息:

Request Error The server encountered an error processing the request. The exception message is 'One or more validation errors were detected during model generation: \tSystem.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'User_LastUpdatedBy_Source' in relationship 'User_LastUpdatedBy'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'. '. See server logs for more details. The exception stack trace is:

at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo) at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) at System.Data.Entity.Internal.RetryLazy2.GetValue(TInput input) at System.Data.Entity.Internal.LazyInternalContext.InitializeContext() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.InternalSet1.Initialize() at System.Data.Entity.Internal.Linq.InternalSet1.get_InternalContext() at System.Data.Entity.Infrastructure.DbQuery1.System.Linq.IQueryable.get_Provider() at System.Linq.Queryable.Where[TSource](IQueryable1 source, Expression1 predicate) at ProjectTracker.Database.DataAccess.DLAccess.DoesUserExist(String userName) in e:\My Own\Projects\ProjectTracker\Database\ProjectTracker.Database.DataAccess\DLAccess.cs:line 31 at ProjectTracker.Business.BLAccess.BLAccess.DoesUserExists(String userName) in e:\My Own\Projects\ProjectTracker\Business\ProjectTracker.Business.BLAccess\BLAccess.cs:line 37 at ProjectTracker.UI.Web.WS.WebAccess.DoesUserExist(String userName) in e:\My Own\Projects\ProjectTracker\UI\ProjectTracker.UI.Web\WS\WebAccess.svc.cs:line 12 at SyncInvokeDoesUserExist(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)



请告诉我,我在这里做错了什么......

最佳答案

EF 映射约定试图推断 User.CreatedBy 之间的一对一关系和 User.LastUpdatedBy .这将失败,因为这两个导航属性同时使用不是主键的外键表示,并且因为 EF 仅支持共享主键一对一关系。

无论如何,这并不重要,因为您不想要一对一的关系,而是两个一对多的关系:一个用户可以创建许多其他用户,一个用户可以修改许多其他用户。

要实现这一点,您必须通过使用 Fluent API 显式定义两个关系来覆盖约定:

modelBuilder.Entity<User>()
    .HasRequired(u => u.CreatedBy)  // this could be a problem, see below
    .WithMany()
    .HasForeignKey(u => u.CreatedByUserId);

modelBuilder.Entity<User>()
    .HasOptional(u => u.LastUpdatedBy)
    .WithMany()
    .HasForeignKey(u => u.LastUpdatedByUserId);

可能需要制作 CreatedBy可选,即 CreatedByUserId必须是 int? 类型并且在上面的映射中,您必须替换 HasRequired来自 HasOptional ,因为否则您将无法在不违反 FK 约束的情况下创建第一个用户。

也许你可以应用一个技巧,比如使用 CreatedByUserId 在数据库中直接创建第一个用户。允许 NULL值,然后将该用户分配为他自己的创建者,然后更改数据库架构,以便 NULL是禁止的。

编辑

有关“EF 映射约定尝试推断 User.CreatedByUser.LastUpdatedBy 之间的一对一关系”的更多详细信息:

当 EF 在启动期间分析您的模型类时,它使用
  • 您使用 Fluent API 的配置,
  • 您应用的数据注释,
  • 从导航属性和属性名称推断关系的一组特定约定。

  • 除非使用 Fluent API 或数据注释明确指定,否则将应用这些设置。您可以在此处找到全套约定:http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions(v=vs.103).aspx

    如果您是原件 User类是 AssociationInverseDiscoveryConvention 应用于您的模型并检测一对一关系。文档说:

    Convention to detect navigation properties to be inverses of each other when only one pair of navigation properties exists between the related types.



    “只有一个”导航属性是 CreatedByUser指的是User - 在 User是第二个导航属性 LastUpdatedBy指回 User . (这有点令人困惑,因为“相关类型”是相同的 - UserUser ,但这里的约定适用于不同类型之间的相同方式。)因为两者都是引用(而不是集合)EF 假设关系必须是一对一的(而不是一对多或多对多)。

    有时,约定不会按照您的意愿推断出这种关系。然后您必须使用 Fluent API 或数据注释覆盖映射约定。 (在您的示例中注释是不够的,您必须在此处使用 Fluent API。)

    关于.net - Entity Framework 代码第一个自加入, 'Multiplicity is not valid in Role',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14726190/

    相关文章:

    c# - 为什么 Entity Framework 6 不支持 Discriminator 的显式过滤?

    c# - Entity Framework 代码首先为正数添加约束

    entity-framework - Entity Framework 代码首先添加不需要的外键列

    c# - Linq to entities 无法识别我的实体类型

    c# - 使用存储过程连接数据库中的 4 个表?

    c# - 安装程序与。桌面应用程序

    c# - EF Core RC2 最终版本 : No database provider has been configured for this DbContext

    entity-framework - Entity Framework 4 ObjectContext 生命周期

    entity-framework - Entity Framework 6.1 将我的数据库放在哪里?

    c# - 使用两个线程写入文本框