在 EF6 ASP.NET MVC 5 中处理多对多关系并从导航属性检索属性到列表的最佳方法

发布于 2025-01-17 22:55:47 字数 3265 浏览 1 评论 0原文

几年前,我从以前的开发人员那里接手了一个项目,并一直在这个系统中工作,添加内容以及重新配置它的某些方面。我最近发现的事情是我尚未处理的多对多关系。

我有两个表:

ECAnalysis - 其中包含给定仪器的有效且有效的分析。

ECAnalyte - 包含活性且有效的分析物。

一项分析可以有多种分析物,而一种分析物可以有多种分析(如果我以正确的方式思考这一点)。

表说明

我的 MySQL 数据库中还有一个中间表,名为 ECAnalysisToECAnalyte,它只包含每个表的主键。

ECAnalysisToECAnalyte 表

由于实体数量较多,EF 代码被配置为通用存储库。因此,为了从系统中获取数据以及导航属性,有一种方法可以获取所有数据:

 public virtual async Task<IList<T>> GetAllAsync<T>(params Expression<Func<T, object>>[] navigationProperties) where T : class
        {
            try
            {
                using (var db = new EntitiesContext())
                {
                    List<T> list;

                    IQueryable<T> dbQuery = db.Set<T>();

                    foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
                        dbQuery = dbQuery.Include<T, object>(navigationProperty);

                    list = await dbQuery.AsNoTracking().ToListAsync<T>();


                    return list;
                }

            }
            catch (ArgumentNullException ex)
            {
                throw new InvalidOperationException($"Invalid state: {typeof(T).Name} DbSet is null.", ex);
            }
        }

此方法适用于所有正常类型的关系和实体,但似乎不适用于多对多关系。

在我的主应用程序中调用它的方式如下:

var data = (from a in await Manager.GetAllAsync<ECAnalysis>(n => n.ECAnalyte)
            select a);

我现在的任务是获取给定分析的分析物列表并将它们传递到视图。我的第一个问题是,当我按原样使用 AsNoTracking() 的方法时,出现异常:

When an object is returned with a NoTracking merge option, Load can only be called when the EntityCollection or EntityReference does not contain objects.

如果我删除 AsNoTracking() 根据我的观点,我得到了正确的分析物列表,但还有另一个例外:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

我如何获取此分析物列表是这样的......我知道它可能不是最干净或最有效的,所以容忍我:

 public async Task<JsonResult> GetAnalytes(string sampleType)
        {
            var analysis = (from a in await Manager.AllAsync<ECAnalysis>(b => b.ECAnalyte)
                            where a.Method == "IC" && a.Media == sampleType + " - ANIONS"
                            select a).ToList();

            var ecAnalytes = analysis.FirstOrDefault().ECAnalyte.ToList();

            var analyteList = new List<string>();

            foreach (var item in ecAnalytes)
            {
                analyteList.Add(item.Name);
            };

            return Json(analysis, JsonRequestBehavior.AllowGet);
    //this is being called from an Ajax method
        }

所以我的问题是:

多对多关系是否根据我想要的使用方式正确配置?

有没有更好的方法来获取给定分析的分析物列表,并且不会给我带来例外?

A few years ago I took over a project from a previous developer and have been working my way through this system and adding to it as well as reconfiguring some aspects of it. The latest thing I've uncovered was a many to many relationship that I haven't handled yet.

I have two tables:

ECAnalysis - which contains active and valid analyses for a given instrument.

ECAnalyte - which contains active and valid analytes.

One analysis can have many analytes whereas one analyte can be on many analyses (if I'm thinking about this in a correct way from what was left for me).

Table Description

There is also an intermediate table in my MySQL database called ECAnalysisToECAnalyte which just contains the primary keys of each table.

ECAnalysisToECAnalyte Table

The EF code is configured as such to be a generic repository because of the large number of entities. So to get data out of the system along with navigation properties there is a method that gets all of the data:

 public virtual async Task<IList<T>> GetAllAsync<T>(params Expression<Func<T, object>>[] navigationProperties) where T : class
        {
            try
            {
                using (var db = new EntitiesContext())
                {
                    List<T> list;

                    IQueryable<T> dbQuery = db.Set<T>();

                    foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
                        dbQuery = dbQuery.Include<T, object>(navigationProperty);

                    list = await dbQuery.AsNoTracking().ToListAsync<T>();


                    return list;
                }

            }
            catch (ArgumentNullException ex)
            {
                throw new InvalidOperationException(
quot;Invalid state: {typeof(T).Name} DbSet is null.", ex);
            }
        }

This method works correctly for all normal types of relationships and entities but it doesn't seem to work for a many to many relationship.

And to call it in my main application it's used in this manner:

var data = (from a in await Manager.GetAllAsync<ECAnalysis>(n => n.ECAnalyte)
            select a);

My task now has been to get a list of analytes for a given analysis and pass them to a view. My first issue is when I use the method as is with the AsNoTracking() I get an exception stating that:

When an object is returned with a NoTracking merge option, Load can only be called when the EntityCollection or EntityReference does not contain objects.

If I remove the AsNoTracking() I get the correct list of analytes to my view but along with another exception:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

How I'm getting this list of analytes is like this...I know it's probably not the cleanest or most efficient so bear with me:

 public async Task<JsonResult> GetAnalytes(string sampleType)
        {
            var analysis = (from a in await Manager.AllAsync<ECAnalysis>(b => b.ECAnalyte)
                            where a.Method == "IC" && a.Media == sampleType + " - ANIONS"
                            select a).ToList();

            var ecAnalytes = analysis.FirstOrDefault().ECAnalyte.ToList();

            var analyteList = new List<string>();

            foreach (var item in ecAnalytes)
            {
                analyteList.Add(item.Name);
            };

            return Json(analysis, JsonRequestBehavior.AllowGet);
    //this is being called from an Ajax method
        }

So my questions are:

Is the many to many relationship configured properly for how I want to use it?

Is there a better way to get a list of analytes for a given analysis that doesn't give me an exception?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文