简体   繁体   English

无效的列名或Identity_Insert关闭

[英]Invalid Column Name or Identity_Insert off

I have been going rounds all morning with CF EF. 我整个上午都和CF EF一起转转。 I think I have all issues resolved but one and I'm sure this issue is due to my lack of knowledge / understanding. 我认为我已经解决了所有问题,但我确信一个问题是由于我缺乏知识/理解。

The problem is focused around one table and the mapping of said table so I'll give the definitions first then explain the problems. 问题集中在一个表和该表的映射上,因此我先给出定义,然后解释问题。 Here is how the table is defined: 这是表的定义方式:

在此处输入图片说明

Now I have defined the class representation as: 现在,我将类表示形式定义为:

public partial class ExternalForumCredentials : BaseEntity
{
   public virtual int Customer_Id { get; set; }
   public virtual int ExternalForumBoardId { get; set; }
   public virtual string Username { get; set; }
   public virtual string Password { get; set; }
 }

and the mapping: 和映射:

public ExternalForumCredentialsMap()
{
   this.ToTable("ExternalForumCredentials");
   this.HasKey(ef => ef.Id);
   this.HasKey(ef => ef.Customer_Id);
   this.HasKey(ef => ef.ExternalForumBoardId);
   this.Property(ef => ef.Username).IsRequired().HasMaxLength(100);
   this.Property(ef => ef.Password).IsRequired().HasMaxLength(100);

 }

Now I am not showing the controller code as I think the problem lies in my ef config. 现在我没有显示控制器代码,因为我认为问题出在我的ef配置中。 HOWEVER if I am wrong simply tell me what I need to add and I will do so immediately. 但是,如果我错了,只需告诉我我需要添加什么,我会立即这样做。

So...given that ID, Customer_Id, and ExternalForumBoardId are primary keys I defined the mapping as seen above. 所以...鉴于ID,Customer_Id和ExternalForumBoardId是主键,我定义了映射,如上所示。

With this configuration all goes well right up to an insert...then it crashes saying I am trying to do an IDENTITY_INSERT. 使用此配置,一切顺利,直到插入为止……然后崩溃,说我正在尝试执行IDENTITY_INSERT。 OK that makes sense as I am assigning a value to Customer_Id and ExternalForumBoardId in the controller and since the mapping has them as keys there is a conflict. 好的,因为我正在为控制器中的Customer_Id和ExternalForumBoardId分配一个值,并且由于映射将它们作为键,所以存在冲突。

So I change the mapping to: 所以我将映射更改为:

public ExternalForumCredentialsMap()
{
        this.ToTable("ExternalForumCredentials");
        this.HasKey(ef => ef.Id);
        this.Property(ef => ef.Customer_Id);
        this.Property(ef => ef.ExternalForumBoardId);
        this.Property(ef => ef.Username).IsRequired().HasMaxLength(100);
        this.Property(ef => ef.Password).IsRequired().HasMaxLength(100);       
}

Now before I can even perform the insert I get an error: Invalid column name Customer_Id and of course with my limited knowledge I don't understand because I have define Customer_Id. 现在,在执行插入操作之前,我得到一个错误:无效的列名Customer_Id,当然由于我的有限知识,我不理解,因为我已经定义了Customer_Id。

I have also tried HasRequired in the mapping but that won't even compile saying "the type int must be a reference type in order to use it as parameter..." 我也在映射中尝试过HasRequired,但是甚至不会编译说“类型int必须是引用类型,才能将其用作参数...”

The other mapping options such as Ignore don't seem to make sense in this context. 在这种情况下,其他映射选项(如忽略)似乎没有意义。

Any help explaining what I am doing wrong would be much appreciated. 任何帮助解释我做错了的事情将不胜感激。


Db Context Interface: Db上下文接口:

public interface IDbContext 
{
    IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity;

    int SaveChanges();

    IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters)
        where TEntity : BaseEntity, new();

    /// <summary>
    /// Creates a raw SQL query that will return elements of the given generic type.  The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type.
    /// </summary>
    /// <typeparam name="TElement">The type of object returned by the query.</typeparam>
    /// <param name="sql">The SQL query string.</param>
    /// <param name="parameters">The parameters to apply to the SQL query string.</param>
    /// <returns>Result</returns>
    IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters);

    /// <summary>
    /// Executes the given DDL/DML command against the database.
    /// </summary>
    /// <param name="sql">The command string</param>
    /// <param name="timeout">Timeout value, in seconds. A null value indicates that the default value of the underlying provider will be used</param>
    /// <param name="parameters">The parameters to apply to the command string.</param>
    /// <returns>The result returned by the database after executing the command.</returns>
    int ExecuteSqlCommand(string sql, int? timeout = null, params object[] parameters);
   }
}

and: 和:

public static class DbContextExtensions {
    /// <summary>
    /// Loads the database copy.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="context">The context.</param>
    /// <param name="currentCopy">The current copy.</param>
    /// <returns></returns>
    public static T LoadDatabaseCopy<T>(this IDbContext context, T currentCopy) where T : BaseEntity {
        return InnerGetCopy(context, currentCopy, e => e.GetDatabaseValues());
    }

    private static T InnerGetCopy<T>(IDbContext context, T currentCopy, Func<DbEntityEntry<T>, DbPropertyValues> func) where T : BaseEntity {
        //Get the database context
        DbContext dbContext = CastOrThrow(context);

        //Get the entity tracking object
        DbEntityEntry<T> entry = GetEntityOrReturnNull(currentCopy, dbContext);

        //The output 
        T output = null;

        //Try and get the values
        if (entry != null) {
            DbPropertyValues dbPropertyValues = func(entry);
            if(dbPropertyValues != null) {
                output = dbPropertyValues.ToObject() as T;
            }
        }

        return output;
    }

    /// <summary>
    /// Gets the entity or return null.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="currentCopy">The current copy.</param>
    /// <param name="dbContext">The db context.</param>
    /// <returns></returns>
    private static DbEntityEntry<T> GetEntityOrReturnNull<T>(T currentCopy, DbContext dbContext) where T : BaseEntity {
        return dbContext.ChangeTracker.Entries<T>().Where(e => e.Entity == currentCopy).FirstOrDefault();
    }

    private static DbContext CastOrThrow(IDbContext context) {
        DbContext output = (context as DbContext);

        if(output == null) {
            throw new InvalidOperationException("Context does not support operation.");
        }

        return output;
    }

    /// <summary>
    /// Loads the original copy.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="context">The context.</param>
    /// <param name="currentCopy">The current copy.</param>
    /// <returns></returns>
    public static T LoadOriginalCopy<T>(this IDbContext context, T currentCopy) where T : BaseEntity {
        return InnerGetCopy(context, currentCopy, e => e.OriginalValues);
    }
}

and the implementation: 和实现:

public class ObjectContext : DbContext, IDbContext
{
    public ObjectContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
        //((IObjectContextAdapter) this).ObjectContext.ContextOptions.LazyLoadingEnabled = true;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //dynamically load all configuration
        System.Type configType = typeof(LanguageMap);   //any of your configuration classes here
        var typesToRegister = Assembly.GetAssembly(configType).GetTypes()
        .Where(type => !String.IsNullOrEmpty(type.Namespace))
        .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(configurationInstance);
        }
        //...or do it manually below. For example,
        //modelBuilder.Configurations.Add(new LanguageMap());



        base.OnModelCreating(modelBuilder);
    }

    /// <summary>
    /// Attach an entity to the context or return an already attached entity (if it was already attached)
    /// </summary>
    /// <typeparam name="TEntity">TEntity</typeparam>
    /// <param name="entity">Entity</param>
    /// <returns>Attached entity</returns>
    protected virtual TEntity AttachEntityToContext<TEntity>(TEntity entity) where TEntity : BaseEntity, new()
    {
        //little hack here until Entity Framework really supports stored procedures
        //otherwise, navigation properties of loaded entities are not loaded until an entity is attached to the context
        var alreadyAttached = Set<TEntity>().Local.Where(x => x.Id == entity.Id).FirstOrDefault();
        if (alreadyAttached == null)
        {
            //attach new entity
            Set<TEntity>().Attach(entity);
            return entity;
        }
        else
        {
            //entity is already loaded.
            return alreadyAttached;
        }
    }

    public string CreateDatabaseScript()
    {
        return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
    }

    public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
    {
        return base.Set<TEntity>();
    }

    public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
    {
        //HACK: Entity Framework Code First doesn't support doesn't support output parameters
        //That's why we have to manually create command and execute it.
        //just wait until EF Code First starts support them
        //
        //More info: http://weblogs.asp.net/dwahlin/archive/2011/09/23/using-entity-framework-code-first-with-stored-procedures-that-have-output-parameters.aspx

        bool hasOutputParameters = false;
        if (parameters != null)
        {
            foreach (var p in parameters)
            {
                var outputP = p as DbParameter;
                if (outputP == null)
                    continue;

                if (outputP.Direction == ParameterDirection.InputOutput ||
                    outputP.Direction == ParameterDirection.Output)
                    hasOutputParameters = true;
            }
        }



        var context = ((IObjectContextAdapter)(this)).ObjectContext;
        if (!hasOutputParameters)
        {
            //no output parameters
            var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();
            for (int i = 0; i < result.Count; i++)
                result[i] = AttachEntityToContext(result[i]);

            return result;

            //var result = context.ExecuteStoreQuery<TEntity>(commandText, parameters).ToList();
            //foreach (var entity in result)
            //    Set<TEntity>().Attach(entity);
            //return result;
        }
        else
        {

            //var connection = context.Connection;
            var connection = this.Database.Connection;
            //Don't close the connection after command execution


            //open the connection for use
            if (connection.State == ConnectionState.Closed)
                connection.Open();
            //create a command object
            using (var cmd = connection.CreateCommand())
            {
                //command to execute
                cmd.CommandText = commandText;
                cmd.CommandType = CommandType.StoredProcedure;

                // move parameters to command object
                if (parameters != null)
                    foreach (var p in parameters)
                        cmd.Parameters.Add(p);

                //database call
                var reader = cmd.ExecuteReader();
                //return reader.DataReaderToObjectList<TEntity>();
                var result = context.Translate<TEntity>(reader).ToList();
                for (int i = 0; i < result.Count; i++)
                    result[i] = AttachEntityToContext(result[i]);
                //close up the reader, we're done saving results
                reader.Close();
                return result;
            }

        }
    }

    /// <summary>
    /// Creates a raw SQL query that will return elements of the given generic type.  The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type.
    /// </summary>
    /// <typeparam name="TElement">The type of object returned by the query.</typeparam>
    /// <param name="sql">The SQL query string.</param>
    /// <param name="parameters">The parameters to apply to the SQL query string.</param>
    /// <returns>Result</returns>
    public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
    {
        return this.Database.SqlQuery<TElement>(sql, parameters);
    }

    /// <summary>
    /// Executes the given DDL/DML command against the database.
    /// </summary>
    /// <param name="sql">The command string</param>
    /// <param name="timeout">Timeout value, in seconds. A null value indicates that the default value of the underlying provider will be used</param>
    /// <param name="parameters">The parameters to apply to the command string.</param>
    /// <returns>The result returned by the database after executing the command.</returns>
    public int ExecuteSqlCommand(string sql, int? timeout = null, params object[] parameters)
    {
        int? previousTimeout = null;
        if (timeout.HasValue)
        {
            //store previous timeout
            previousTimeout = ((IObjectContextAdapter) this).ObjectContext.CommandTimeout;
            ((IObjectContextAdapter) this).ObjectContext.CommandTimeout = timeout;
        }

        var result = this.Database.ExecuteSqlCommand(sql, parameters);

        if (timeout.HasValue)
        {
            //Set previous timeout back
            ((IObjectContextAdapter) this).ObjectContext.CommandTimeout = previousTimeout;
        }

        //return result
        return result;
    }
}

You have another class that has a relationship with ExternalForumCredentials and it hasn't be configured properly. 您还有另一个与ExternalForumCredentials有关系的类,并且该类的配置不正确。 EntityFramework will try its best to guess your conventions, so it's guessing that there is a Customer_Id that it can connect to. EntityFramework将尽最大努力猜测您的约定,因此猜测它可以连接到一个Customer_Id

Go to any maps that are using ExternalForumCredentials and configure them properly. 转到使用ExternalForumCredentials任何地图,并正确配置它们。 For example: 例如:

this.HasMany(ef => ef.ExternalForumCredentials)
    .WithRequired()
    .HasForeignKey(ef => ef.Customer_Id);

暂无
暂无

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

相关问题 SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法为表 [表名] 中的标识列插入显式值 - SqlException: Cannot insert explicit value for identity column in table [Table name] when IDENTITY_INSERT is set to OFF IDENTITY_INSERT设置为OFF - IDENTITY_INSERT is set to OFF 实体框架:当IDENTITY_INSERT设置为OFF时,无法为表&#39;[table]&#39;中的标识列插入显式值 - Entity Framework: Cannot insert explicit value for identity column in table '[table]' when IDENTITY_INSERT is set to OFF 当IDENTITY_INSERT设置为OFF时,无法为表&#39;ActivityInstances中的标识列插入显式值 - Cannot insert explicit value for identity column in table 'ActivityInstances' when IDENTITY_INSERT is set to OFF 当IDENTITY_INSERT设置为OFF时,无法为标识列插入显式值 - Cannot insert explicit value for identity column when IDENTITY_INSERT is set to OFF SqlException:当IDENTITY_INSERT设置为OFF时,无法为表&#39;Recipe&#39;中的Identity列插入显式值 - SqlException: Cannot insert explicit value for identity column in table 'Recipe' when IDENTITY_INSERT is set to OFF 当IDENTITY_INSERT设置为OFF时,无法在表&#39;MyTableName&#39;中为标识列插入显式值 - Cannot insert explicit value for identity column in table 'MyTableName' when IDENTITY_INSERT is set to OFF SqlException:当IDENTITY_INSERT设置为OFF时,无法为表&#39;AspNetUsers&#39;中的Identity列插入显式值 - SqlException: Cannot insert explicit value for identity column in table 'AspNetUsers' when IDENTITY_INSERT is set to OFF 当IDENTITY_INSERT设置为OFF时,无法在表&#39;candidatedetails&#39;中为identity列插入显式值 - Cannot insert explicit value for identity column in table 'candidatedetails' when IDENTITY_INSERT is set to OFF 当 IDENTITY_INSERT 设置为 OFF 时,无法为标识列插入显式值。 (实体框架核心) - Cannot insert explicit value for identity column when IDENTITY_INSERT is set to OFF. (Entity Framework Core)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM