C# EF POCO中可为空的通用密钥

C# EF POCO中可为空的通用密钥,c#,entity-framework,generics,C#,Entity Framework,Generics,考虑一个可定制的数据模型,其中模型的键是通用的。模型如下所示: public class Model<TKey, TUserKey> { public virtual TKey Id { get; set; } public virtual TUserKey UserId { get; set; } public virtual TUserKey NullableUserId { get; set; } // ? } public class Model&l

考虑一个可定制的数据模型,其中模型的键是通用的。模型如下所示:

public class Model<TKey, TUserKey> {
    public virtual TKey Id { get; set; }
    public virtual TUserKey UserId { get; set; }
    public virtual TUserKey NullableUserId { get; set; } // ?
}
public class Model<TKey, TUserKey, TOptionalUserKey> {
    public virtual TKey Id { get; set; }
    public virtual TUserKey UserId { get; set; }
    public virtual TOptionalUserKey NullableUserId { get; set; }
}
解决这一问题的明显方法是采用如下通用布局:

public class Model<TKey, TUserKey> {
    public virtual TKey Id { get; set; }
    public virtual TUserKey UserId { get; set; }
    public virtual TUserKey NullableUserId { get; set; } // ?
}
public class Model<TKey, TUserKey, TOptionalUserKey> {
    public virtual TKey Id { get; set; }
    public virtual TUserKey UserId { get; set; }
    public virtual TOptionalUserKey NullableUserId { get; set; }
}
公共类模型{
公共虚拟密钥Id{get;set;}
公共虚拟TUserKey用户标识{get;set;}
公共虚拟TopationalUserKey NullableUserId{get;set;}
}
这意味着您可以将其实例化为
,就像两个示例一样

问题是-我是否可以避免执行后一种操作并使用更多泛型类型参数?在我的现实生活模型中,我有两种可以为null的密钥类型,可选的
TKey
和可选的
TUserKey
,如果可能的话,我想“神奇地”处理这一点,而不是依赖用户传入其密钥的可为null的变体

注意。EF的
.Property(..).isoOptional()
在这里不起作用,因为这意味着模型不能代表数据,和/或实现者需要在模型生成器重写中记住它


NB2。用于创建的另一个包装类将检测类或值,然后创建它也将不起作用,因为正是这个类将直接映射到
DbSet
,我们需要传递它。

我能快速找到的最佳方法(因为C#没有提供一些C++的模板特性,这些特性可以让您在一个类中实现这一点)是有两个通用类:

public class Model<TKey, TUserKey> where TUserKey : struct
{
    public virtual TKey Id { get; set; }
    public virtual TUserKey UserId { get; set; }
    public virtual TUserKey? NullableUserId { get; set; }   
}

public class Model2<TKey, TUserKey> where TUserKey : class
{
    public virtual TKey Id { get; set; }
    public virtual TUserKey UserId { get; set; }
    public virtual TUserKey NullableUserId { get; set; }
}
公共类模型,其中TUserKey:struct
{
公共虚拟密钥Id{get;set;}
公共虚拟TUserKey用户标识{get;set;}
公共虚拟TUserKey?NullableUserId{get;set;}
}
公共类模型2,其中TUserKey:class
{
公共虚拟密钥Id{get;set;}
公共虚拟TUserKey用户标识{get;set;}
公共虚拟TUserKey NullableUserId{get;set;}
}

您不能使用错误的键类型(由于约束),并且在这两种类型中都会出现可为null的行为,但这并不像我希望的那样优雅。

尝试在属性上将其设置为可为null,如下所示。public virtual nullable NullableUserId{get;set;}@StephenBrickner谢谢,但正如我已经提出的问题一样,这可能不起作用,因为它可能是值类型,也可能不是值类型。@Fabjan它已经可以为null了?没有意义?这不是我想做的。人们可以传入引用或值类型作为泛型参数,我需要处理这两种类型才能为null。@Fabjan我相信他说通用(T)需要同时支持引用类型和值类型。此属性的数据库字段的类型是什么?从技术上讲,您可以完全删除type param并将该字段设置为字符串。如果它是对象,请在保存之前将其序列化为json。在这两种情况下,您都必须尝试解析它,以确定要处理的类型+1,我尝试的解决方案不同,谢谢!很显然,这个问题的要点是让它变得优雅,因为它本身并不是一个问题,额外的泛型类型可以被添加。它是可怕的:(同意-但没有部分模板特化的C++,我不认为有更好的路线。这正是我的恐惧!(唯一的另一种(稍微干净一点的方式)是,正如我在“NB2”中所说的,在它上面有一个类,根据参数是否是值类型创建泛型,但仍然归结为有两个模型(尽管一个是另一个的抽象)并降低了解决方案的优雅度。悲伤的时刻!