自定义实体 ID 数据类型在插入时失败
我正在尝试在数据层中使用顺序int
ids,并使用 hashids.nets.net < /a>库在我的服务器代码和UI层中给我类似YouTube的“ Hashed” ID。我通过创建下面显示的自定义struct
来使它起作用我想。然后,我会在任何数据列属性使用此数据类型时自动创建valueConverter
onModeLcreating
。
最终,与查询对象无处可完美地工作,包括外键等。但是,仅在尝试插入新对象时,我也会在下面显示错误。我的目标是让实体框架忽略hashiDentifier
inserts上的值,如果其值为默认
。如果值为0
,它也会忽略int
。我希望数据库使用Identity
我设置在此处,然后使用valueeconverter
我设置的实体框架来生成新密钥我的hashientifier
的形式,在插入以外的所有其他情况下都可以使用。
public partial struct HashIdentifier : IEquatable<HashIdentifier>, IEquatable<int>, IComparable<HashIdentifier>, IComparable<int>
{
private static Hashids _hashids = new("seed", 11);
private int _value;
public int Value => _value;
public HashIdentifier(in int value)
{
_value = value;
}
public override string ToString()
{
return _hashids.Encode(Value);
}
public static HashIdentifier Parse(in string value)
{
if (TryParse(value, out HashIdentifier _result))
return _result;
throw new InvalidIdentifierException(value);
}
public static bool TryParse(in string value, out HashIdentifier result)
{
int[] _decode = _hashids.Decode(value);
if (_decode.Length == 0)
{
result = default;
return false;
}
result = new(_decode[0]);
return true;
}
public int CompareTo(HashIdentifier other)
{
return CompareTo(other.Value);
}
public int CompareTo(int other)
{
return Value.CompareTo(other);
}
public override bool Equals(object obj)
{
switch (obj)
{
case int _a: return Equals(_a);
case HashIdentifier _a: return Equals(_a);
}
return false;
}
public bool Equals(int other)
{
return other == Value;
}
public bool Equals(HashIdentifier other)
{
return other.Value == Value;
}
public static bool operator ==(int left, HashIdentifier right)
{
return right.Equals(left);
}
public static bool operator !=(int left, HashIdentifier right)
{
return !(left == right);
}
public static explicit operator int(HashIdentifier value)
{
return value.Value;
}
public static explicit operator HashIdentifier(int value)
{
return new(value);
}
}
我插入的错误:
当SIDENTITY_INSERT设置为OFF
时
hashindentifier
时,在表'testtable'中的身份列的明确值 0 有效。它确实在达到异常之前,确实会访问valueConverter
。那么,为什么它认为我要设定一个明确的价值呢?
这不是
我已经搜索Internet和Stackoverflow的解决方案的副本,但我还没有找到解决方案。我是不是正在寻找一种使用Identity_insert
的方法。请仔细了解我的问题。我希望实体框架能够像切换键使用自定义结构之前一样工作。
我的表格架构如下:
CREATE TABLE [dbo].[TestTable]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Sequence] [int] NULL,
[CreatedDate] [datetime] NOT NULL
CONSTRAINT [PK_TestTable]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
更新
这似乎是一个已知问题,根据 Microsoft文档
当前具有转换的密钥属性无法使用生成的键值。投票 github问题#11597 要删除此限制。
I'm trying to use sequential INT
ids in my data layer and use the Hashids.NET library to give me YouTube-like 'hashed' ids in my server code and UI layers. I got it to work by creating the custom struct
shown below which resides in memory as an Int32
and prints to string
as a hashed id exactly as I want. I then automatically create a ValueConverter
in OnModelCreating
any time any data column property uses this data type.
This ends up working flawlessly with querying objects, includes, foreign keys, etc. However, only upon trying to insert new objects, I get the error also shown below. My goal is to get Entity Framework to ignore the HashIdentifier
value on inserts if its value is default
. The same way it would ignore an int
if the value is 0
. I want the database to be generating the new keys with the IDENTITY
I set there, and then Entity Framework to use the ValueConverter
I have set up to use the new values in the form of my HashIdentifier
, which already works in every other case other than inserts.
public partial struct HashIdentifier : IEquatable<HashIdentifier>, IEquatable<int>, IComparable<HashIdentifier>, IComparable<int>
{
private static Hashids _hashids = new("seed", 11);
private int _value;
public int Value => _value;
public HashIdentifier(in int value)
{
_value = value;
}
public override string ToString()
{
return _hashids.Encode(Value);
}
public static HashIdentifier Parse(in string value)
{
if (TryParse(value, out HashIdentifier _result))
return _result;
throw new InvalidIdentifierException(value);
}
public static bool TryParse(in string value, out HashIdentifier result)
{
int[] _decode = _hashids.Decode(value);
if (_decode.Length == 0)
{
result = default;
return false;
}
result = new(_decode[0]);
return true;
}
public int CompareTo(HashIdentifier other)
{
return CompareTo(other.Value);
}
public int CompareTo(int other)
{
return Value.CompareTo(other);
}
public override bool Equals(object obj)
{
switch (obj)
{
case int _a: return Equals(_a);
case HashIdentifier _a: return Equals(_a);
}
return false;
}
public bool Equals(int other)
{
return other == Value;
}
public bool Equals(HashIdentifier other)
{
return other.Value == Value;
}
public static bool operator ==(int left, HashIdentifier right)
{
return right.Equals(left);
}
public static bool operator !=(int left, HashIdentifier right)
{
return !(left == right);
}
public static explicit operator int(HashIdentifier value)
{
return value.Value;
}
public static explicit operator HashIdentifier(int value)
{
return new(value);
}
}
The error I get on inserts:
Cannot insert explicit value for identity column in table 'TestTable' when IDENTITY_INSERT is set to OFF
The value of the HashIdentifier
at the time of the insert was effectively 0
. And it does call into the ValueConverter
right before hitting the exception. So why does it think I am setting an explicit value?
This is not a duplicate
I've already searched the internet and StackOverflow for solutions and I haven't found one. I am not looking for a way to use IDENTITY_INSERT
. Please understand my issue carefully. I want Entity Framework to work as it did before I switched my keys to use custom structs.
My table schema is as follows:
CREATE TABLE [dbo].[TestTable]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Sequence] [int] NULL,
[CreatedDate] [datetime] NOT NULL
CONSTRAINT [PK_TestTable]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Update
This appears to be a known issue according to the Microsoft Documentation
Currently key properties with conversions cannot use generated key values. Vote for GitHub issue #11597 to have this limitation removed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论