简体   繁体   English

实体框架-使用类继承创建模型

[英]Entity Framework - Model creation using class inheritance

Having a bit of a strange issue when trying to create a model object using inheritance with code first entity framework 6.1. 尝试通过代码优先实体框架6.1使用继承创建模型对象时遇到一个奇怪的问题。

I've created a base User class in a shared code library and in my application I've created another User class inherited from the base class. 我已经在共享代码库中创建了一个基础User类,在我的应用程序中,我还创建了另一个继承自该基础类的User类。

Base User class: 基本用户类别:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using CSAMLib.Data.Entity;
using CSAMLib.Security.Cryptography;
using System.ComponentModel.DataAnnotations;

namespace CSAMLib.Security
{
    public class User : BaseEntity, CSAMLib.Security.IUser
    {
        public bool Active { get; set; }

        [Display(Name = "First name")]
        public String FirstName { get; set; }

        [Display(Name = "Last name")]
        public String LastName { get; set; }

        [Display(Name = "Full name")]
        public String FullName { get { return (FirstName == null ? String.Empty : FirstName + " ") + (LastName ?? String.Empty); } }

        [Display(Name = "Login", Prompt = "someone@example.com")]
        public String Login { get; set; }

        [Display(Name = "Email address")]
        public String EmailAddress { get; set; }

        public byte[] Password { get; set; }

        [Display(Name = "Last login date")]
        public DateTime? LastLoginDate { get; set; }

        [Display(Name = "Logged in")]
        public bool CurrentlyLoggedIn { get; set; }

        [Display(Name = "Signature filepath")]
        public byte[] SignatureFileContent { get; set; }

        [Display(Name = "Signature filename")]
        public String SignatureFileName { get; set; }

        [Display(Name = "Signature content")]
        public String SignatureContentType { get; set; }

        public String Qualification { get; set; }

        [NotMapped]
        public String NewPassword { get; set; }
        [NotMapped]
        public PasswordPolicy PasswordPolicy { get; set; }

        public virtual ICollection<UserRole> UserRoles
        {
            get;
            set;
        }

        public byte[] Salt { get; set; }

    }
}

User class: 用户类别:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace Muro.Models
{
    [Table("Users")]
    public class User : CSAMLib.Security.User
    {
        public bool ClientUser { get; set; }

        [Display(Name = "Company")]
        [ForeignKey("Company")]
        public Int64? CompanyID { get; set; }
        public virtual Company Company { get; set; }

        public new ICollection<UserRole> UserRoles
        {
            get;
            set;
        }


        public SystemUser CreateNewUser(string userName, string emailAddress, string firstName, string lastName)
        {
            var user = new Muro.Models.User();
            user.Login = userName;
            user.EmailAddress = emailAddress;
            user.Active = false;
            user.CurrentlyLoggedIn = false;
            user.FirstName = firstName;
            user.LastName = lastName;
            return user;
        }
    }

DBContext: DBContext:

public DbSet<Muro.Models.User> Users { get; set; }

This approach resulted in the following error when running update-database: 运行更新数据库时,此方法导致以下错误:

The type 'CSAMLib.Security.User' and the type 'Muro.Models.User' both have the same simple name of 'User' and so cannot be used in the same model. 类型“ CSAMLib.Security.User”和类型“ Muro.Models.User”都具有相同的简单名称“ User”,因此不能在同一模型中使用。 All types in a given model must have unique simple names. 给定模型中的所有类型都必须具有唯一的简单名称。 Use 'NotMappedAttribute' or call Ignore in the Code First fluent API to explicitly exclude a property or type from the model. 使用“ NotMappedAttribute”或在Code First fluent API中调用“忽略”以从模型中明确排除属性或类型。

I could understand this as both the class names share simple names. 我可以理解这一点,因为两个类名都共享简单名称。 My next approach was to rename the application User class to SystemUser in order to get around this issue. 我的下一个方法是将应用程序User类重命名为SystemUser,以解决此问题。 However, I'm now getting the following error and not quite sure where to go next with this. 但是,我现在遇到以下错误,并且不确定接下来要去哪里。

Error: 错误:

System.InvalidOperationException: Sequence contains more than one element
   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Entity.ModelConfiguration.Conventions.ForeignKeyPrimitivePropertyAttributeConvention.Apply(PropertyInfo memberInfo, ConventionTypeConfiguration configuration, ForeignKeyAttribute attribute)
   at System.Data.Entity.ModelConfiguration.Conventions.PropertyAttributeConfigurationConvention`1.<.ctor>b__0(ConventionTypeConfiguration ec)
   at System.Data.Entity.ModelConfiguration.Conventions.TypeConvention.ApplyCore(Type memberInfo, ModelConfiguration modelConfiguration)
   at System.Data.Entity.ModelConfiguration.Conventions.TypeConventionBase.Apply(Type memberInfo, ModelConfiguration modelConfiguration)
   at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
   at System.Data.Entity.ModelConfiguration.Conventions.Convention.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
   at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
   at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapEntityType(Type type)
   at System.Data.Entity.ModelConfiguration.Mappers.NavigationPropertyMapper.Map(PropertyInfo propertyInfo, EntityType entityType, Func`1 entityTypeConfiguration)
   at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapEntityType(Type type)
   at System.Data.Entity.ModelConfiguration.Mappers.NavigationPropertyMapper.Map(PropertyInfo propertyInfo, EntityType entityType, Func`1 entityTypeConfiguration)
   at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapEntityType(Type type)
   at System.Data.Entity.DbModelBuilder.<>c__DisplayClassd.<MapTypes>b__7(Type type)
   at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
   at System.Data.Entity.Utilities.IEnumerableExtensions.Each[T](IEnumerable`1 ts, Action`1 action)
   at System.Data.Entity.DbModelBuilder.MapTypes(EdmModel model)
   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.RetryLazy`2.GetValue(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.LazyInternalContext.get_ModelBeingInitialized()
   at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
   at System.Data.Entity.Utilities.DbContextExtensions.<>c__DisplayClass1.<GetModel>b__0(XmlWriter w)
   at System.Data.Entity.Utilities.DbContextExtensions.GetModel(Action`1 writeXml)
   at System.Data.Entity.Utilities.DbContextExtensions.GetModel(DbContext context)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.GetMigrator()
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Sequence contains more than one element

SystemUser class: SystemUser类:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace Muro.Models
{
    [Table("Users")]
    public class SystemUser : CSAMLib.Security.User
    {
        public bool ClientUser { get; set; }

        [Display(Name = "Company")]
        [ForeignKey("Company")]
        public Int64? CompanyID { get; set; }
        public virtual Company Company { get; set; }

        public new ICollection<SystemUserRole> UserRoles
        {
            get;
            set;
        }


        public SystemUser CreateNewUser(string userName, string emailAddress, string firstName, string lastName)
        {
            var user = new Muro.Models.SystemUser();
            user.Login = userName;
            user.EmailAddress = emailAddress;
            user.Active = false;
            user.CurrentlyLoggedIn = false;
            user.FirstName = firstName;
            user.LastName = lastName;
            return user;
        }
    }
}

DBContext: DBContext:

public DbSet<SystemUser> Users { get; set; }

Has anyone seen the same behaviour and has any tips to get around this? 有没有人看到过相同的行为,并有解决此问题的提示?

Thanks! 谢谢!

I think the first problem has nothing to do with the second one (as you already solved that). 我认为第一个问题与第二个问题无关(因为您已经解决了)。

The exception tells you what the problem should be: 异常告诉您问题应该是什么:
You call SingleOrDefault() on a collection which seems to have more then one item, which is not allowed by this method. 您在一个似乎有一个以上项目的集合上调用SingleOrDefault() ,这是该方法所不允许的。 You can do the following to solve this: 您可以执行以下操作来解决此问题:

  • use FirstOrDefault to get the first element of the collection matching 使用FirstOrDefault获取集合匹配的第一个元素
  • adapt the search pattern so it only returns zero or one lement 调整搜索模式,使其仅返回零或一个元素

If you show us the actual call to SingleOrDefault we may can help you better, but I can't find such a call in the posted code... 如果您向我们显示对SingleOrDefault的实际调用,我们可能会更好地为您提供帮助,但在发布的代码中找不到这样的调用...

这是因为您的类具有[Table()]属性的相同值,尽管您重命名了类,但是您仍试图创建两个具有相同名称的表,这导致“序列包含多个元素”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM