我遇到了这个错误,无法找到解决方法。我尝试了几件事,但无法提出解决方案。
这是我的问题:
代码:
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服务调用时获得的异常详细信息:
请求错误服务器在处理请求时遇到错误。 异常消息是“检测到一个或多个验证错误 在模型生成期间:\ tSystem.Data.Entity.Edm.EdmAssociationEnd :: 多重性在角色'User_LastUpdatedBy_Source'中无效 关系'User_LastUpdatedBy'。因为依赖角色 属性不是关键属性,是上限 依赖角色的多样性必须为'*'。 ”。请参阅服务器日志 更多细节。异常堆栈跟踪是:
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest) providerManifest,DbProviderInfo providerInfo)at System.Data.Entity.DbModelBuilder.Build(的DbConnection providerConnection) System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)at System.Data.Entity.Internal.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()at System.Data.Entity.Internal.Linq.InternalSet1.get_InternalContext() at System.Data.Entity.Infrastructure.DbQuery
1.System.Linq.IQueryable.get_Provider() 在System.Linq.Queryable.Where [TSource](IQueryable1 source, Expression
1谓词)at at ProjectTracker.Database.DataAccess.DLAccess.DoesUserExist(字符串 e:\ My中的userName) 自己的\项目\ ProjectTracker \数据库\ ProjectTracker.Database.DataAccess \ DLAccess.cs:行 31在ProjectTracker.Business.BLAccess.BLAccess.DoesUserExists(String e:\ My中的userName) 自己的\项目\ ProjectTracker \企业\ ProjectTracker.Business.BLAccess \ BLAccess.cs:行 37在ProjectTracker.UI.Web.WS.WebAccess.DoesUserExist(String e:\ My中的userName) 自己的\项目\ ProjectTracker \ UI \ ProjectTracker.UI.Web \ WS \ WebAccess.svc.cs:行 12在SyncInvokeDoesUserExist(Object,Object [],Object [])处 System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(对象 实例,对象[]输入,对象[]&输出) 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)
请告诉我,我在这里做错了什么......
答案 0 :(得分:11)
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
值,然后将此用户指定为他自己的创建者,然后更改数据库模式以便{ {1}}被禁止。
修改强>
有关“ EF映射惯例的详细信息尝试推断NULL
与User.CreatedBy
之间的一对一关系。”:
当EF在启动期间分析您的模型类时,它使用
除非使用Fluent API或数据注释明确指定,否则将应用这些中心集。您可以在此处找到完整的约定:http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions(v=vs.103).aspx
如果您的原始User.LastUpdatedBy
课程是适用于您的模型的AssociationInverseDiscoveryConvention
并且检测到一对一的关系。文档说:
检测导航属性的惯例是每个的反转 其他当时只存在一对导航属性 相关类型。
{only} User
中的“{1}”导航属性CreatedBy
引用User
- User
中的第二个导航属性User
这可以追溯到LastUpdatedBy
。 (这有点令人困惑,因为“相关类型”是相同的 - User
和User
,但这里的约定适用于不同类型之间的相同方式。)因为两者都是引用(而不是集合) )EF假设关系必须是一对一的(而不是一对多或多对多)。
有时,约定不会根据需要推断关系。然后,您必须使用Fluent API或数据注释覆盖映射约定。 (在您的示例中,注释是不够的,您必须在此处使用Fluent API。)