从 sql server 读取数据时检测到自引用循环

Posted

技术标签:

【中文标题】从 sql server 读取数据时检测到自引用循环【英文标题】:Self referencing loop detected while reading data from sql server 【发布时间】:2020-01-07 21:34:42 【问题描述】:

我正在尝试使用以下代码每秒从数据库中读取数据:

public class DBChangeService : DelegatingHandler, IHostedService

    private Timer _timer;
    public SqlDependencyEx _sqlDependency;
    private readonly IHubContext<SignalServer> _hubcontext;
    private readonly IServiceScopeFactory _scopeFactory;
    string connectionString = "";
    public IConfiguration Configuration  get; 

    public DBChangeService(IConfiguration configuration, IHubContext<SignalServer> hubcontext, IServiceScopeFactory scopeFactory)
    
        _scopeFactory = scopeFactory;
        _hubcontext = hubcontext;
        Configuration = configuration;
        connectionString = Configuration.GetConnectionString("DefaultConnection");
    

    public Task StartAsync(CancellationToken cancellationToken)
    
        _timer = new Timer(Heartbeat, null, 0, 1000);
        return Task.CompletedTask;
    


    public void Heartbeat(object state)
    
         _hubcontext.Clients.All.SendAsync("SBSystemBrodcasting", SBSystemApps());

    

    public async Task<List<SomeModel>> SBSystemApps()
    
        var data = new List<SomeModel>();

        using (var scope = _scopeFactory.CreateScope())
        
            using (SqlConnection connection = new SqlConnection(connectionString))
            
                string commandText = @"SELECT 
                        a.name as AppName,
                        a.state as AppState,
                        a.created_at as AppCreatedAt,
                        a.updated_at as AppUpdatedAt,
                        a.foundation as AppFoundation,

                        s.name as SpaceName,
                        o.name as OrgName
                    FROM
                        apps as a
                    INNER JOIN
                        spaces as s ON a.space_guid = s.space_guid
                    INNER JOIN
                        organizations as o ON s.org_guid = o.org_guid
                    where s.name = 'system' and o.name = 'system' and a.foundation = 2";

                try
                
                    SqlCommand cmd = new SqlCommand(commandText, connection);

                    await connection.OpenAsync();
                    using (DbDataReader reader = await cmd.ExecuteReaderAsync())
                    
                        while (await reader.ReadAsync())
                        
                            var sqlresult = new SomeModel
                            
                                AppName = reader["AppName"].ToString(),
                                AppState = reader["AppState"].ToString(),
                                AppCreatedAt = Convert.ToDateTime(reader["AppCreatedAt"]),
                                AppUpdatedAt = Convert.ToDateTime(reader["AppUpdatedAt"]),
                                AppFoundation = Convert.ToInt32(reader["AppFoundation"]),
                                SpaceName = reader["SpaceName"].ToString(),
                                OrgName = reader["OrgName"].ToString(),
                            ;

                            data.Add(sqlresult);
                        

                    
                
                finally
                
                    connection.Close();
                

                return data;
            
        
    


    public Task StopAsync(CancellationToken cancellationToken)
    
        //Timer does not have a stop. 
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    

出现以下错误:

Newtonsoft.Json.JsonSerializationException:自引用循环 检测到具有类型的属性“任务” 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder1+AsyncStateMachineBox1[System.Collections.Generic.List`1[TestApp.Models.SomeModel],TestApp.Services.DBChangeService+d__11]'。

我已经尝试了在 *** 上可以找到的几乎所有可能的解决方案,但没有一个有效

在启动中:

services.AddMvc().AddJsonOptions(options =>
            
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            );

在我的班级标题上,我尝试使用[JsonObject(IsReference = true)],但没有任何想法适合我?

型号:

[JsonObject(IsReference = true)]
    public partial class SomeModel
    
        public string AppName  get; set; 
        public string AppState  get; set; 
        public DateTime AppCreatedAt  get; set; 
        public DateTime AppUpdatedAt  get; set; 
        public int AppFoundation  get; set; 
        public string OrgName  get; set; 
        public string SpaceName  get; set; 
    

【问题讨论】:

如果 JSON.Net 抛出错误(以及那个特定的错误),那么很可能是您的模型并且与其余部分有 0 关系。我没有看到它的猜测是你在两个类之间有一个循环引用,这让它很头疼。删除不相关的代码并发布模型。 【参考方案1】:
_hubcontext.Clients.All.SendAsync("SBSystemBrodcasting", SBSystemApps());

问题是您使用Task 调用SendAsync。这不是 API 的设计用途。您应该通过您想要使用的实际有效负载

有多种方法可以解决这个问题。一种是使用:

_hubcontext.Clients.All.SendAsync("SBSystemBrodcasting", SBSystemApps().GetAwaiter().GetResult());

虽然我建议阅读 this guidance 了解为什么这不是一个好主意。

另一种方法是更改​​ SBSystemApps 使其同步(即返回 List&lt;T&gt; 而不是 Task&lt;List&lt;T&gt;&gt;

【讨论】:

以上是关于从 sql server 读取数据时检测到自引用循环的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Core 中检测到自引用循环 [重复]

为 WebApi 2 中的属性检测到自引用循环

sql server 2005数据库检索时,出现无法为此请求检索数据的问题

在 SQL Server 中读取 JSON 数据时无法从字符串转换为日期时间

从 SQL Server 插入一些数据的表中读取数据的问题

从 SQL Server 读取 nvarchar 时带菱形的问号