EF CodeFirst:参数@objname不明确或声称@objtype(COLUMN)错误

问题描述 投票:47回答:8

我有一个名为EducationTypes的表和一个名为EducationType的实体,我重命名了一个实体属性,现在我经常得到Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong。我该如何解决这个问题?

生成的SQL脚本:

EXECUTE sp_rename @objname = N'dbo.EducationTypes.nvarchar', @newname = N'EducationTypeTitle', @objtype = N'COLUMN'
c# entity-framework ef-code-first ef-migrations
8个回答
30
投票

如果您正在使用Code First并且拥有(一个)现有的迁移脚本,并且正在尝试覆盖已被删除的更改(即重命名列),那么您将获得该错误输出。最简单的方法是删除迁移脚本,通过NuGet添加迁移,然后更新数据库。


10
投票

这是因为当自动创建表格时,名称与类别(模型)名称冲突与其他保留或生成的名称。

考虑到EF代码优先创建干预表以使用派生干预表的表名来关联2个或更多个表,因此当您使用使用类似干预表的名称的类名时,我们将得到这样的模糊错误。

例如,如果您有一个具有Answer导航属性的Question类,则内部模型元数据将包含一个名为QUESTION_ANSWER的引用

要解决此问题,请尝试更改类名(用于生成表)并确保其唯一性。


3
投票

当我尝试使用Sql(“...”)方法重命名迁移脚本中的外键时,我得到了Entity Framework 6。我的解决方法是在名称周围使用方括号:

即改变这个:

sp_rename 'FK_dbo.tablename_dbo.othertablename_fieldname', 'FK_dbo.tablename_dbo.othertablenewname_fieldnewname', 'object'

......对此:

sp_rename '[FK_dbo.tablename_dbo.othertablename_fieldname]', 'FK_dbo.tablename_dbo.othertablenewname_fieldnewname', 'object'

然后SQL Server能够找到外键。


2
投票

花了太多时间试图弄清楚为什么在生产数据库上发生这种情况我只能通过mylittlesql访问。无法重现问题,但是从sp_rename的位编写了这个脚本,所以当下次我确实发现确切原因时它会发生。是的是矫枉过正,但可能会帮助别人。

如果您以某种方式设法将'['或']'变为存储在sys.columns中的实际列名,(?'nvarchar'作为列名????),则会出现问题。 PARSENAME不处理[]并返回null,因此sp_rename不起作用。

这只会帮助诊断“列”案例的问题,错误代码为15248,这是我遇到此问题的地方:

declare @objname nvarchar(1035) = N'dbo.EducationTypes.nvarchar' -- input to sp_rename
declare @newname sysname = N'EducationTypeTitle' -- input to sp_rename

declare @UnqualOldName  sysname,
@QualName1      sysname,
@QualName2      sysname,
@QualName3      sysname,
@OwnAndObjName  nvarchar(517),  
@SchemaAndTypeName  nvarchar(517),  
@objid          int,
@xtype          nchar(2),
@colid          int,
@retcode        int

select @UnqualOldName = parsename(@objname, 1),
        @QualName1 = parsename(@objname, 2),
        @QualName2 = parsename(@objname, 3),
        @QualName3 = parsename(@objname, 4)
print 'Old Object Name = ''' + convert(varchar,isnull(@UnqualOldName ,'')) + ''''
-- checks that parsename is getting the right name out of your @objname parameter
print 'Table name:'
if @QualName2 is not null
begin
print QuoteName(@QualName2) +'.'+ QuoteName(@QualName1)
select @objid = object_id(QuoteName(@QualName2) +'.'+ QuoteName(@QualName1))
end
else
begin
print QuoteName(@QualName1)
select @objid = object_id(QuoteName(@QualName1))
end
-- check if table is found ok
print 'Table Object ID = ''' + convert(varchar,isnull(@objid ,-1)) + ''''
select @xtype = type from sys.objects where object_id = @objid
print '@xtype = ''' + convert(varchar,isnull(@xtype,'')) + ''' (U or V?)'
if (@xtype in ('U','V'))
begin
print 'select @colid = column_id from sys.columns where object_id = ' + 
    convert(varchar,isnull(@objid,0)) + ' and name = ''' +
        @UnqualOldName + ''''

    select * from sys.columns where object_id = @objid -- and name = @UnqualOldName
    select @colid = column_id from sys.columns 
    where object_id = @objid and name = @UnqualOldName
    print 'Column ID = ''' + convert(varchar,isnull(@colid,-1)) + ''''
end

这将在“消息”选项卡(SSMS或您正在使用的任何内容)和“结果”选项卡中的表字段中输出一些有用的消息。

祝好运。


1
投票

重构后我也遇到了同样的问题。对我来说,问题是由重构的迁移引起的。

结果是无法执行另一次迁移,因为迁移是通过搜索旧名来查找表。

恢复迁移中的更改解决了此问题。


1
投票

在迁移标题中避开保留字或类名。

当我将迁移命名为“Init” - 重命名为“InitialCreate”并完成所有工作时,就发生了这种情况


0
投票

实际上,当您刚删除数据库时,也会发生此错误,并且您的上下文没有意识到您的数据库不存在。

我重新创建了数据库,现在错误已解决。

附:当您尝试运行update-database时,请确保检查数据库是否仍然存在


0
投票

对我来说,它发生在:

  • 添加了新的迁移(migratoin1)
  • 在本地数据库上更新
  • 然后删除了相同的迁移(migratoin1)
  • 然后添加同名(migratoin1)另一个迁移
  • 然后应用到本地数据库并发布。

删除迁移文件(migratoin1)解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.