1

我一直在开发一个使用 LINQ 来管理简单 SQLite 数据库的 C# 程序。数据库包含在我的代码中由不同类表示的不同表中。这就是我创建表的方式:

    public ITable<Doctors> Doctors => GetTable<Doctors>();

    public ITable<Patients> Patients=> GetTable<Patients>();

    public ITable<Prescriptions> Prescriptions=>GetTable<Prescriptions>();

    public ITable<Assistants> Assistants=> GetTable<Assistants>();

    public ITable<Medicines> Medicines => GetTable<Medicines>();

    public ITable<General_medicines> General_medicines=> GetTable<General_medicines>();

    public ITable<Stocks> Stocks=> GetTable<Stocks>();

    public ITable<Dosages> Dosages=> GetTable<Dosages>();

    public ITable<Recipes> Recipes=> GetTable<Recipes>();

    public ITable<Prescriptions_MP> Prescriptions_MP=> GetTable<Prescriptions_MP>();

现在,我想创建一个 LINQ 查询(在一个单独的类中),在其中我在所有这些表中获得不同的属性,并将它们放在一个 IEnumerable 中,以便以后扫描。为此,我进行如下操作:

public IEnumerable<Therapy> TakePrescriptions()
{
            HealthDataContext DbContext = DbFactory.Create();
            var dbPrescriptions = DbContext.GetTable<Prescriptions>();
            IEnumerable<Prescriptions> prescriptions= dbPrescriptions.AsEnumerable();

            var dbPatients= DbContext.GetTable<Patients>();
            IEnumerable<Pazienti> patients= dbPatients.AsEnumerable();

            var dbPrescrizioniMP = DbContext.GetTable<Prescriptions_MP>();
            IEnumerable<Prescriptions_MP> prescriptionsMP = dbPrescriptionsMP .AsEnumerable();

            var dbRecipes = DbContext.GetTable<Recipes>();
            IEnumerable<Recipes> recipes= dbRecipes .AsEnumerable();

            var dbMedicines= DbContext.GetTable<Medicines>();
            IEnumerable<Medicines> medicines= dbMedicines.AsEnumerable();

            var dbGeneral_medicines = DbContext.GetTable<General_medicines>();
            IEnumerable<General_medicines> general_medicines= dbGeneral_medicines.AsEnumerable();

            var dbDosages = DbContext.GetTable<Dosages>();
            IEnumerable<Dosages> dosages= dbDosages .AsEnumerable();

            var query = from p in patients
                            join pr in prescriptions_MP on p.Id equals pr.Patient
                            join pre in prescriptions on pr.Prescription equals pre.Id
                            join fc in medicines on pre.Medicine equals fc.Id
                            join fg in general_medicines on fc.Medicine equals fg.Id
                            join ds in dosages on fg.Id equals ds.General_Medicine
                            where p.Doctor== IdDoctor
                            select new
                            {
                                IdDoctor, //int
                                p.Name, //string
                                pr.Prescription, //int
                                pre.Id, //int
                                fc.Format, //string 
                                fc.Administration, //string
                                fc.Downloadable, //boolean
                                fc.Full_stomach, //boolean
                                nameM= fg.Name, //string
                                ds.Quantity, //int
                                ds.Hour //string
                            };


            List < Therapy> therapy = new List<Therapy>();



            foreach(var object in query)
            {
                Therapy t = new Therapy(IdDoctor, object.Name, object.Prescription, object.Id, object.Format, object .Administration, object.Downloadable, object.Full_stomach, object.nameM, object.Quantity, object.Hour);

                therapy.Add(t);

            }

            return therapy;
}

现在,当我尝试加载应显示结果列表的页面时,我得到InvalidOperationException: An open reader is associated with this command。在更改 CommandText 属性之前关闭它。foreach操作中。

当我尝试调试时,我可以看到我在查询之前创建的表里面有项目,但是查询的结果是 NULL

我试图处置 DBContext,但后来我得到了这个异常:ObjectDisposedException:IDataContext 已处置,请参阅https://github.com/linq2db/linq2db/wiki/Managing-data-connection对象名称:'DataConnection'。

4

2 回答 2

1

您应该AsEnumerable()从查询中使用的表中删除调用,因为它们强制 linq2db 将它们作为单独的查询执行。

这有两个后果:

  • 它尝试通过单个数据库连接启动多个查询,这是不受支持的,你会得到InvalidOperationException
  • 让我们想象一下它会起作用(例如,您替换AsEnumerable()ToList()从每个查询中读取所有数据)。在这种情况下,它会将所有数据加载到应用程序中并在 C# 代码中执行连接 - 这将导致性能非常差,尤其是在您需要丢弃一些不符合连接条件的数据的情况下。
于 2018-11-19T10:44:20.303 回答
1

您收到的错误“打开的阅读器与此命令相关联。在更改 CommandText 属性之前关闭它”,表示打开了多个阅读器。但是,看着您的查询,似乎一位读者对您的一项查询开放。然而现实却不同。您有 5 个表,因此每个表与另一个表具有一对多的关系。例如,患者表与处方表具有一对多的关系。作为一个病人可以有多个处方。

因此,仅考虑这两个表,我们首先有一个查询来加载所有患者,然后对每个患者进行另一个查询来加载其所有处方,这意味着如果您有 N 个患者,则转换为 1 + N 查询,加载 1所有患者,N 加载每个患者的处方。

现在给定代码中的 5 级连接,计算一下,您可以看到有多少潜在的开放读者。数据是按需加载的,这意味着一旦您遍历查询结果,就会激活读取器,这是为了避免大量内存使用,降低性能成本,因此在您的 foreach 循环中您开始遍历对象, 数据是真实被获取的。

为了解决这个问题,您可以尝试在查询结束时转换 ToList 以鼓励绑定(因此急切加载),或者作为评论者之一建议将 MultipleActiveResultSets=true 传递给您的连接字符串。

于 2018-08-24T18:47:06.230 回答