【问题标题】:Entity Framework: how to set the type of a column as uniqueidentifier with Fluent API实体框架:如何使用 Fluent API 将列的类型设置为唯一标识符
【发布时间】:2018-08-30 11:18:51
【问题描述】:

我使用 Entity Framework 6,代码优先。

我有一个由我无权访问的框架 (Azure Mobile Server SDK) 创建的列 <string> Id

public abstract class EntityData
{
    [Key]
    [TableColumn(TableColumnType.Id)]
    public string Id { get; set; }

    ...
}

如果我不执行任何操作,则此类列将在 SQL Server 中映射为 nvarchar(MAX)

我已经能够使用 Fluent API 中的这个 sn-p 将其变成 char(36)

PropertyConventionConfiguration pkConf = modelBuilder.Properties<string>().Where(p => p.Name == "Id");
pkConf.Configure(p => p.IsUnicode(false));
pkConf.Configure(p => p.HasMaxLength(36));
pkConf.Configure(p => p.IsFixedLength());

我想设置为uniqueidentifier

如何使用类似的 Fluent API 代码 sn-p 做到这一点?

非常感谢!

【问题讨论】:

  • 如果将 Id 更改为 Guid 类型而不是字符串会发生什么?您显然需要删除长度限制。 Guid 应该映射到唯一标识符。
  • 我无法触及类定义,因为它在 Azure SDK 中,而不是我的代码中
  • 在下面发布响应作为答案。
  • 这解决了您的问题吗?
  • @MehdiIbrahim 请检查我的 cmets 你的答案

标签: entity-framework-6 azure-mobile-services uniqueidentifier ef-fluent-api ef-code-first-mapping


【解决方案1】:

您可以使用自定义值转换器或利用内置的 GuidToStringConverterdocs.microsoft.com/en-us/ef/core/modeling/value-conversions。一些旁注——你应该创建一个继承自这个抽象类的类。这不仅提供了抽象层,还允许您更精确地控制存储和访问数据的方式。此外,您可能知道,GUID 会产生可怕的 PK!

编辑:

如果您使用的是 EF 6,则此功能将不可用。因此,您将需要创建包装属性或使用存储过程。这是一个例子,示例代码可以在这里找到:https://github.com/ibrahm2/entityframework6-map-string-to-guid

方法一:包装器属性

  1. 创建一个继承自EntityData 的类。对于这个例子,我们称之为WrapperTable 例如
  2. 添加一个名为Id 类型为Guid 的属性,并使用new 修饰符屏蔽基本Id 属性。让它从基类返回Id 的转换版本为Guid。这将掩盖基本属性。这不是最佳实践,因此如果您对此感到不舒服,另一种选择是创建一个新属性,例如称为 Key 环绕 Id
  3. 如果您的配置,将继承的类映射到EntityDate 表。

    modelBuilder.Entity().ToTable("EntityData");

方法二:存储过程

  1. 创建一个将 varchar 作为 Id 字段参数的存储过程
  2. 将存储过程映射到实体的插入函数例如:

    modelBuilder.Entity().MapToStoredProcedures(prop=>prop.Insert(sp=>sp.HasName("sp_InsertTable").Parameter(pm => pm.Id, "@id")));

  3. 让存储过程将 varchar 插入到您的 uniqueidentifier 字段中。

【讨论】:

  • 嗨@MehdiIbrahim,感谢您的建议,但我有几个问题:1)我想从String更改为Guid,而不是从Guid更改为String! 2) EF Core 中存在值转换,我只能使用“普通”EF 6
  • 更新了我的答案。抱歉,我认为 EF6 没有更简洁的选项。
  • 顺便说一句,你试过 pkConf.Configure(p => p.HasColumnType("uniqueidentifier")); ?
  • 感谢@MehdiIbrahim 的提议,不幸的是它给了我这个问题:[错误 2019:指定的成员映射无效。 'LTSyncMobile.Models.TodoItem' 类型中成员 'Id' 的类型 'Edm.String[Nullable=False,DefaultValue=,MaxLength=36,Unicode=False,FixedLength=True]' 与 'SqlServer.uniqueidentifier[ 'CodeFirstDatabaseSchema.TodoItem' 类型中成员 'Id' 的 Nullable=False,DefaultValue=]'。]
  • 这是一个单独的问题,应该是一个单独的问题。我不认为这里的任何人都会有动力在你遇到的每一个问题上提供无限的帮助 - 相关或不相关的,而不承认你已经收到了原始问题的两个解决方案。我 100% 确定我在这里的回答——两种选择——对于遇到类似问题的其他人来说都是非常有价值的。祝你好运!
【解决方案2】:

给你:

 modelBuilder.Entity<TodoItem>().Property(t => t.Id).HasColumnType("UniqueIdentifier");

更多信息供您参考:

Configuring the Data Type of a Database Column

【讨论】:

  • 嗨,李,感谢您的建议,不幸的是它给了我这个问题:[错误 2019:指定的成员映射无效。 'LTSyncMobile.Models.TodoItem' 类型中成员 'Id' 的类型 'Edm.String[Nullable=False,DefaultValue=,MaxLength=36,Unicode=False,FixedLength=True]' 与 'SqlServer.uniqueidentifier[ 'CodeFirstDatabaseSchema.TodoItem' 类型中成员 'Id' 的 Nullable=False,DefaultValue=]'。]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多