实体框架代码首次自联接,'Multiplicity is not valid in Role'



我被这个错误卡住了,找不到解决方案。我试了好几种方法,但都没能想出解决办法。

这是我的问题:

代码:

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

以下是我从网络服务调用它时得到的异常详细信息

请求错误服务器在处理请求时遇到错误。异常消息为"检测到一个或多个验证错误在模型生成过程中:\t系统。数据实体Edm。EdmAssociationEnd::多重性在中的角色"User_LastUpdatedBy_Source"中无效关系"User_LastUpdatedBy"。因为从属角色属性不是关键属性Dependent Role的多重性必须为"*"。"。"。请参阅的服务器日志更多细节。异常堆栈跟踪为:

在系统中。数据实体DbModelBuilder。生成(DbProviderManifestproviderManifest、DbProviderInfo providerInfo)系统数据实体DbModelBuilder。生成(DbConnectionproviderConnection)系统数据实体内部的LazyInternalContext。CreateModel(LazyInternalContextinternalContext)系统数据实体内部的位于的RetryLazy 2.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.InternalSet 1.Initialize()系统数据实体内部的林克。InternalSet 1.get_InternalContext() at System.Data.Entity.Infrastructure.DbQuery 1.System.Linq.IQueryable.get_Provider()在系统中。林克。可查询。其中[TSource](IQueryable 1 source, Expression 1谓词)位于ProjectTracker。数据库DataAccess。DLAccess。DoesUserExist(字符串用户名)Own\Projects\ProjectTracker\Database\ProjectTracker。数据库DataAccess\DLAccess.cs:line31在ProjectTracker。商业BLAccess。BLAccess。DoesUserExists(字符串用户名)Own\Projects\ProjectTracker\ Business\ProjectTracker。商业BLAccess\BLAccess.cs:line37在ProjectTracker。UI。网状物WS-WebAccess.DesUserExist(字符串用户名)Own\Projects\ProjectTracker\UI\ProjectTracker。UI。Web\WS\WebAccess.svc.cs:line12位于的SyncInvokeDoesUserExist(Object,Object[],Object[])系统ServiceModel。调度员。SyncMethodInvoker。Invoke(对象实例,Object[]输入,Object[]&输出)系统ServiceModel。调度员。DispatchOperationRuntime。InvokeBegin(MessageRpc&rpc)系统ServiceModel。调度员。不可变调度运行时。ProcessMessage5(MessageRpc&rpc)系统ServiceModel。调度员。不可变调度运行时。ProcessMessage31(MessageRpc&rpc)。ServiceModel。调度员。消息Rpc。进程(布尔值isOperationContextSet)

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

EF映射约定试图推断User.CreatedByUser.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约束的情况下创建第一个用户。

可能你可以应用一个技巧,比如用允许NULL值的CreatedByUserId直接在DB中创建第一个用户,然后将该用户分配为他自己的创建者,然后更改DB模式,从而禁止NULL

编辑

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

当EF在启动期间分析您的模型类时,它使用

  1. 您使用Fluent API的配置
  2. 您应用的数据注释
  3. 从导航属性和属性名称推断关系的一组特定约定

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

如果是原始User类,则应用于模型并检测一对一关系的是AssociationInverseDiscoveryConvention。文件上写着:

将导航属性检测为每个属性的倒数的约定当相关类型。

"唯一"的一对导航属性是User中的CreatedBy,它引用User,而在User中是第二个导航属性LastUpdatedBy,它引用回User。(这有点令人困惑,因为"相关类型"是相同的——UserUser,但这里的约定与不同类型之间的约定相同。)因为两者都是引用(而不是集合),EF假设关系必须是一对一(而不是一对多或多对多)。

有时约定无法根据您的需要推断关系。然后您必须使用Fluent API或数据批注覆盖映射约定。(注释在您的示例中是不够的,您必须在此处使用Fluent API。)

相关内容

  • 没有找到相关文章

最新更新