简体   繁体   English

Linq查询多个表

[英]Linq query with multiple tables

Trying to type a Linq expression that will include information from two tables. 尝试键入包含两个表中信息的Linq表达式。

        var articles = db.Articles;
        var articlescores = db.ArticleScores;

articles table has the title field 文章表有标题字段

articles.title

the articlescores table has the ActualCity field and ArticleID field articlescores表具有ActualCity字段和ArticleID字段

articlescores.ActualCity
artickescores.ArticleID (which links to articles table)

I need to .Count() the articlescores.ActualCity field, then store the highest counted city in a string along with articles.title 我需要.Count()articlescores.ActualCity字段,然后最高计数城市存储在一个字符串连同articles.title

Basically articles viewed most by a city. 基本上是一个城市最受欢迎的文章。

Sample Data: 样本数据:

ArticleScore table: ArticleScore表:

    ID articleID City  (Note: articleID is not dependent on City, I just wrote it this way)
    1    1       New York   
    2    2       Boston
    3    1       New York
    4    1       New York
    5    1       New York
    6    2       Boston

article table: 文章表:

ID title
1  TitleOneOfArticles
2  TitleTwoOfArticles

Expected output (because New York has a count of 4, Boston only has 2): 预期输出(因为纽约有4个,波士顿只有2个):

TitleOneOfArticles, NewYork(4)
      ^^              ^^     ^
    title            City   Count

Only one line of output is expected. 预计只有一行输出。

Your question is self-contradictory and it's also missing some key information. 你的问题是自相矛盾的,它也缺少一些关键信息。 So I'm going to take a guess. 所以我要猜一猜。

  • You did not mention linq to what you are using. 你没有提到你正在使用的linq。 Are you using Entity Framework? 您使用的是Entity Framework吗? Lightspeed? 光速? Something else? 别的什么? I'm assuming it's Entity Framework 我假设它是实体框架
  • You say that you need Basically articles viewed most by a city , but then you go ahead and give somewhat different example. 你说你需要基本上最受城市观看的文章 ,但是你继续前进并给出一些不同的例子。 I'm going to assume that it is the most viewed article by cities is what you are after 我将假设它是城市中观看次数最多的文章
  • You say that articleID is not dependent on City but then proceed given an example where is one to one relationship between a City and articleID. 你说articleID不依赖于City,但后来举例说明了City和articleID之间的一对一关系。

Here is how I understand a sample ArticleScore dataset: 以下是我对ArticleScore数据集示例的理解:

    ID articleID  City  
     ?    1       New York   
     ?    1       New York
     ?    1       New York
     ?    1       Boston
     ?    2       New York
     ?    2       Boston
     ?    2       Boston

In this dataset there are 3 views for article 1 in NewYork and 1 view of article 2. Likewise, in Boston, there are 2 views of article 2 and 1 view of article 1. 在这个数据集中,NewYork的第1条有3个视图,第2条有1个视图。同样,在波士顿,有2条视图,第2条视图和第1条视图。

Based on this data, I'm assuming you want to get something like this 根据这些数据,我假设你想得到这样的东西

TitleTwoOfArticles, Boston(2)
TitleOneOfArticles, NewYork(3)

This table above signifies that In Boston the most viewed article is article 2 with the total of 2 views. 上表显示在波士顿,观看次数最多的文章是第2条,总共有2个观看次数。 In NewYork, the most viewed article is 1 with the total of 3 view. 在NewYork,观看次数最多的文章是1,总共3个视图。 Note that the total number of views for an article across all cities is not shown here. 请注意,此处未显示所有城市中文章的总观看次数。

A created a code sample to test the scenario above, for it I used: 创建了一个代码示例来测试上面的场景,因为我使用了:

  • Visual Studio 2013 / .net 4.5 Visual Studio 2013 / .net 4.5
  • Entity Framework 6 实体框架6

Here is the code: 这是代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;

namespace SO22928136
{
    public interface IMyDbContext : IDisposable
    {
        IDbSet<Article> Articles { get; set; }
        IDbSet<ArticleScore> ArticleScores { get; set; }
        int SaveChanges();
    }

    public class MyDbContext : DbContext, IMyDbContext
    {
        public IDbSet<Article> Articles { get; set; }
        public IDbSet<ArticleScore> ArticleScores { get; set; }

        static MyDbContext()
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());
        }

        public MyDbContext(string connectionString) : base(connectionString)
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Configurations.Add(new ArticleConfiguration());
            modelBuilder.Configurations.Add(new ArticleScoreConfiguration());
        }
    }

    public class Article
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public virtual ICollection<ArticleScore> ArticleScores { get; set; }
        public Article()
        {
            ArticleScores = new List<ArticleScore>();
        }
    }

    public class ArticleScore
    {
        public int Id { get; set; }
        public int ArticleId { get; set; }
        public string ActualCity { get; set; }
        public virtual Article Article { get; set; }
    }

    internal class ArticleConfiguration : EntityTypeConfiguration<Article>
    {
        public ArticleConfiguration()
        {
            ToTable("Article");
            HasKey(x => x.Id);
            Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(x => x.Title).HasColumnName("Title").IsOptional();
        }
    }

    internal class ArticleScoreConfiguration : EntityTypeConfiguration<ArticleScore>
    {
        public ArticleScoreConfiguration()
        {
            ToTable("ArticleScore");
            HasKey(x => x.Id);
            Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(x => x.ArticleId).HasColumnName("ArticleId").IsRequired();
            Property(x => x.ActualCity).HasColumnName("ActualCity").IsOptional().HasMaxLength(10);
            HasRequired(a => a.Article).WithMany(b => b.ArticleScores).HasForeignKey(c => c.ArticleId);
        }
    }


    class Program
    {
        static void Main()
        {
            MyDbContext context = new MyDbContext("Data Source=(local);Initial Catalog=SO22928136;Integrated Security=True;");
            CreateTestData(context);

            var countOfArticlesPerCity = context.ArticleScores.GroupBy(s => new {s.ArticleId, s.ActualCity}).Select(g => new {g.Key.ArticleId, g.Key.ActualCity, Count = g.Count()});
            var highestArticleCountPerCity = countOfArticlesPerCity.GroupBy(x => x.ActualCity).Select(g => g.OrderByDescending(x => x.Count).FirstOrDefault());
            var highestArticleCountPerCityWithArticleTitle = context.Articles.Join(highestArticleCountPerCity, x => x.Id, p => p.ArticleId, (x, p) => new { x.Title, p.ActualCity, p.Count });

            foreach (var line in highestArticleCountPerCityWithArticleTitle)
            {
                Console.WriteLine("{0}, {1}({2})",line.Title,line.ActualCity, line.Count);
            }

        }

        private static void CreateTestData(MyDbContext context)
        {
            Article articleOne = new Article { Title = "TitleOneOfArticles" };
            Article articleTwo = new Article { Title = "TitleTwoOfArticles" };

            articleOne.ArticleScores.Add(new ArticleScore { ActualCity = "NewYork" });
            articleOne.ArticleScores.Add(new ArticleScore { ActualCity = "NewYork" });
            articleOne.ArticleScores.Add(new ArticleScore { ActualCity = "NewYork" });
            articleOne.ArticleScores.Add(new ArticleScore { ActualCity = "Boston" });

            articleTwo.ArticleScores.Add(new ArticleScore { ActualCity = "NewYork" });
            articleTwo.ArticleScores.Add(new ArticleScore { ActualCity = "Boston" });
            articleTwo.ArticleScores.Add(new ArticleScore { ActualCity = "Boston" });

            context.Articles.Add(articleOne);
            context.Articles.Add(articleTwo);
            context.SaveChanges();
        }
    }
}

The linq queries that is of most interest to you are in the main method. 您最感兴趣的linq查询是主要方法。 Modify the connection string to point to your test server. 修改连接字符串以指向测试服务器。 Make sure that the database name you are using DOES NOT EXIST because database with this name WILL BE DROPPED. 确保您使用的数据库名称不存在,因为具有此名称的数据库将被删除。 Be careful. 小心。

When the program runs it drops/creates the specified database and creates the sample schema in it. 程序运行时,它会删除/创建指定的数据库并在其中创建示例模式。 The it proceeds inserting its sample data, as described above. 如上所述,它继续插入其样本数据。 Then the actual query you are interested in follow. 然后是您感兴趣的实际查询。

I split the query to three parts. 我将查询分为三个部分。 Firstly, we group by city name and article id and calculate counts for each line. 首先,我们按城市名称和文章ID进行分组,并计算每行的计数。 Secondly, we select only those lines that have maximum count number for each city. 其次,我们只选择每个城市拥有最大计数的那些行。 Finally, we join with the Article table to get article title from the id. 最后,我们加入Article表,从id获取文章标题。

After that we print out the results. 之后我们打印出结果。 It should be easy to modify the query to return just one line, you just need to add a condition to it. 应该很容易修改查询只返回一行,你只需要为它添加一个条件。

try this linq: 尝试这个linq:

db.Articles
               .Join(db.ArticleScores ,
                   art=> art.ID,
                   scr=> scr.ID,
                   (art, scr) => new { article= art, score= scr})
                   .Where(both => (both.art.ID == cityID))
                   .Select(both => both.score)

the cityId is parameter that you should send cityId是您应该发送的参数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM