.NET中使用EF出现莫名字段缺失的问题

将.Net Framework中几段使用EF相关的代码移植到.NET的项目中,本想省点事,结果碰到莫名的故障,导致浪费不少时间来解决问题。
有两个模型使用Scarffold-Context从数据库中生成,示例如下(均作了适当简化):

//用户表模型
public partial class User
{
    public long Id { get; set; }

    public bool Enabled { get; set; }

    public string Login { get; set; } = null!;

    public string Password { get; set; } = null!;

    public string? Display { get; set; }
}
//角色表模型
public partial class Role
{
    public long Id { get; set; }

    public string Code { get; set; } = null!;

    public string Display { get; set; } = null!;

    public string? Description { get; set; }
}

//用户与角色的关联表模型
public partial class UserRole
{
    public long Id { get; set; }

    public long UserId { get; set; }

    public long RoleId { get; set; }
}

在使用下面的代码进行Role表的所有数据的访问时,突然出现如图错误:

var roles = DbContext.Roles.ToList();
图1. 奇怪的错误出现:无效的列名'UserId'

然而,我们的Role模型里根本没有涉及任何字段名为UserId,查询SQL Server端,确实在执行这一句查询的时候,发送过去的查询是:

SELECT [r].[ID], [r].[Code], [r].[Description], [r].[Display], [r].[UserId]
FROM [Role] AS [r]
ORDER BY [r].[Code]

看起来是EF在屁股后面加了个[r].[UserId]
研究了很久,终于找到扩展模型User的分部类里,添加了一个属性:

private ObservableCollection<Role> roles = [];
public ObservableCollection<Role> Roles
{
    get
    {
        if (roles.Count == 0)
        {
                var db = DbContext ?? AppHelper.DbContext;
                var rs = db.Roles.ToList();
                foreach (var r in rs)
                {
                    r.IsSelected = db.UserRoles.Any(p => p.UserId == Id && p.RoleId == r.Id);
                }

                var rls = rs.OrderBy(o => o.Code);

                foreach (var role in rls)
                {
                    roles.Add(role);
                }
        }

        return roles;
    }
}

要注意的是,在.Net Framework的EF中,并不需要明确声明属性与数据库字段没映射关系,而在.NET中,则需要用[NotMapped]明确声明,这里忘记打上这个标记,所以Scaffold-Context在生成模型的时候,认为User跟Role有一个一对多的映射关系,所以它自动帮我“运作”了一下,给Role模型加了个隐式属性(Shadow Property)UserId。解决办法就是在这个属性前面标上[NotMapped]就解决了。
如下所示:

private ObservableCollection<Role> roles = [];
[NotMapped]
public ObservableCollection<Role> Roles
{
    get
    {
        if (roles.Count == 0)
        {
                var db = DbContext;
                var rs = db.Roles.ToList();
                foreach (var r in rs)
                {
                    r.IsSelected = db.UserRoles.Any(p => p.UserId == Id && p.RoleId == r.Id);
                }

                var rls = rs.OrderBy(o => o.Code);

                foreach (var role in rls)
                {
                    roles.Add(role);
                }
        }

        return roles;
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容