EntityFramework拒绝忘记旧列

时间:2015-09-22 07:55:59

标签: c# entity-framework entity-framework-6 ef-database-first

我使用EntityFramework 6.1.3,数据库优先。我现在希望我选择代码优先......

我有一个包含一些表的数据库。我以前 从这些表中构建了我的edmx。然后我改变了几列的类型并添加了几列。例如,将bit列更改为int列。

我尝试使用right-click -> Update Model from Database从数据库更新我的模型。

似乎无论我做什么,EF都只会像我创建edmx时那样获​​取数据库的状态。我尝试过的事情:

  1. 重新打开Visual Studio
  2. 重建项目
  3. 删除并重新添加实体(大多数人认为应该这样做)
  4. 在Visual Studio关闭并替换它们时,在整个项目中搜索xml或C#中的文本引用到我的列。 (这似乎最初起作用,但是如果我再次尝试从数据库更新它会写入它们)
  5. 重新启动SQL服务
  6. 重新启动机器
  7. "运行自定义工具"关于所有.tt文件(不应该有所作为,但是到底是什么)
  8. 当我右键单击我的实体并选择"表映射"时,它始终显示左侧的旧bit列。

    mapping problem

    这是我的数据库表设计:

    sql table design

    可能需要注意的是,实体正在离开视图,而不是直接离开表格。但是当我正在调查这个问题时,视图实际上是表的select *,我已经确认了powershell,视图返回的类型是int:

    PS> $conn = new-object data.sqlclient.SqlConnection("data source=localhost;initial catalog=dbname;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework")
    PS> $conn.open()
    PS> $query = $conn.createcommand()
    PS> $query.commandtext = "select * from [dbname].[LocalCustom].[viewname]"
    PS> $reader = $query.executereader()
    PS> $reader.getschematable().rows[19]
    
    ColumnName                      : ActiveMember
    ColumnOrdinal                   : 19
    ColumnSize                      : 4
    NumericPrecision                : 10
    NumericScale                    : 255
    IsUnique                        : False
    IsKey                           :
    BaseServerName                  :
    BaseCatalogName                 :
    BaseColumnName                  : ActiveMember
    BaseSchemaName                  :
    BaseTableName                   :
    DataType                        : System.Int32
    AllowDBNull                     : False
    ProviderType                    : 8
    IsAliased                       :
    IsExpression                    :
    IsIdentity                      : False
    IsAutoIncrement                 : False
    IsRowVersion                    : False
    IsHidden                        :
    IsLong                          : False
    IsReadOnly                      : False
    ProviderSpecificDataType        : System.Data.SqlTypes.SqlInt32
    DataTypeName                    : int
    XmlSchemaCollectionDatabase     :
    XmlSchemaCollectionOwningSchema :
    XmlSchemaCollectionName         :
    UdtAssemblyQualifiedName        :
    NonVersionedProviderType        : 8
    IsColumnSet                     : False
    

    我现在的主要问题是...... EF如何知道它曾经是bit类型?它在哪里存储这些数据?当然我也想知道如何使用UI正确更新模型,而不必删除和重新添加实体或我将要拥有的任何其他内容做到更新。

    我对EF非常沮丧:(

2 个答案:

答案 0 :(得分:8)

这是我在使用Entity Framework数据库时经常遇到的情况。当您从数据库进行一些更改时,要更新EF,您应该:

  1. 删除.edmx
  2. 中的修改后的表格
  3. 通过right-click -> Update Model from Database -> check that table
  4. 将该表重新添加到.edmx

答案 1 :(得分:3)

好吧,即使没有任何更改,也只需编辑/更新您的视图即可。 EF不会更新未经修改的项目。

只要您没有更改/更新视图,但基本表格,EF无法检测是否需要更改任何内容。我确实认为这种行为是为了防止每次都完全重建模型。

由于OP希望了解"为什么",我做了一些测试。

首先,我创建了一个表格和一个" SELECT *"观点:

create table TableToChange(rowKey bigint IDENTITY(1,1) not null, myBitFlag bit null, myIntFlag int)
go
create view SelectStarOnChangingTable as SELECT * FROM TableToChange
go

然后我对使用以下函数创建的sys对象和列进行了一些检查:

select * 
from sys.all_objects AO 
    join sys.all_columns AC on AC.object_id=AO.object_id
where AO.object_id in (--insert your objet_ids here--)

对表对象进行一些小的更改:

alter table TableToChange
drop column myBitFlag
go
alter table TableToChange
add myBitFlag int
go

如果再次运行架构查询,您会注意到更新后的列在USER_TABLE行和VIEW行中没有相同的类型(56 vs 104)

更改SelectStarOnChangingTable视图而不进行更改将强制SQL Server更新。

我们现在有一个罪魁祸首:SQL Server存储视图的列类型,阻止EF更新其模型,即使实体是从头开始重建。