【问题标题】:Linq join returning duplicate resultsLinq join 返回重复的结果
【发布时间】:2017-12-29 13:08:49
【问题描述】:

我正在使用 LINQ 尝试获取我的角色的所有衣服。

我的查询如下所示:

var characterList = from characters in ContextFactory.Instance.Characters
                    where characters.UserId == user.Id

                    join traits in ContextFactory.Instance.CharacterTraits
                    on characters.Id equals traits.CharacterId
                    join clothes in ContextFactory.Instance.CharacterClothes
                    on characters.Id equals clothes.CharacterId
                    select new { 
                        characters.Id, 
                        characters.Name, 
                        characters.Gender, 
                        characters.Level, 
                        characters.Money, 
                        characters.Bank, 
                        characters.LastLogin, 
                        characters.PlayedTime, 
                        traits, 
                        clothes };

然后我将它序列化为在 javascript 中用作 JSON。

此代码为我拥有的每件衣服返回一个用户,我希望它将所有衣服分组到一个数组中。我怎么能这样做?

当前结果:

谢谢

【问题讨论】:

    标签: c# linq join duplicates


    【解决方案1】:

    为此,您需要使用GroupJoin注意在连接末尾添加了into

    var characterList = from characters in ContextFactory.Instance.Characters
                        where characters.UserId == user.Id
                        join t in ContextFactory.Instance.CharacterTraits
                        on characters.Id equals t.CharacterId into traits 
                        join c in ContextFactory.Instance.CharacterClothes into clothes
                        on characters.Id equals c.CharacterId
                        select new { /* As before */ }
    

    在 MSDN 上阅读更多信息:Perform Grouped Joins

    请注意,如果您使用的是 EF,则无需编写连接。正确定义导航属性并使用Include 将在更少的工作中为您提供所需的内容。


    最后,请注意,即使有Where 条件,这也会返回IEnumerable<> 的结果。如果您只想要一条包含所有这些信息的记录,那么在最后添加一个 FirstOrDefault 或更好的方法,然后在查询中删除 where 子句并执行以下操作:

    var character = (from characters in ContextFactory.Instance.Characters
                     join t in ContextFactory.Instance.CharacterTraits
                     on characters.Id equals t.CharacterId into traits 
                     join c in ContextFactory.Instance.CharacterClothes into clothes
                     on characters.Id equals c.CharacterId
                     select new { /* As before */ }).FirstOrDefault( x=> x.id = user.Id);
    

    【讨论】:

    • @Wuzi - 这个解决方案有帮助您解决问题吗?
    • 我试过了,但由于某种原因,我得到了一个错误(无效的表达式术语'into'),然后我看到你提到了导航属性,我对 EF 还很陌生,所以我开始研究它。我终于设法用导航属性完成了我需要的事情!谢谢你。基本上我所做的只是将它添加到我的角色模型中:public virtual ICollection<CharacterClothes> Clothes { get; set; }
    【解决方案2】:

    见下面的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                User user = new User();
    
                var characterList = (from characters in ContextFactory.Instance.Characters
                where characters.UserId == user.Id
                join traits in ContextFactory.Instance.CharacterTraits
                on characters.Id equals traits.CharacterId
                join clothes in ContextFactory.Instance.CharacterClothes
                on characters.Id equals clothes.CharacterId
                select new { characters = characters, traits = traits, clothes = clothes })
                .GroupBy(x => x.characters.Id)
                .Select(x => new { 
                    id = x.FirstOrDefault().characters.Id, 
                    name = x.FirstOrDefault().characters.Name, 
                    gender = x.FirstOrDefault().characters.Gender, 
                    level = x.FirstOrDefault().characters.Level, 
                    money = x.FirstOrDefault().characters.Money, 
                    bank = x.FirstOrDefault().characters.Bank, 
                    lastLogin = x.FirstOrDefault().characters.LastLogin, 
                    playedTime = x.FirstOrDefault().characters.PlayedTime, 
                    traits = x.FirstOrDefault().traits, 
                    clothes = x.Select(y => y.clothes.clothes).ToArray()
                }).FirstOrDefault();
    
            }
        }
    
        public class ContextFactory
        {
            public static Instance Instance = null;
        }
        public class Instance
        {
            public List<Characters> Characters;
            public List<CharactersTraits> CharacterTraits;
            public List<CharactersClothes> CharacterClothes;
        }
        public class Characters
        {
            public int Id;
            public int UserId;
            public string Name;
            public string Gender;
            public string Level;
            public string Money;
            public string Bank;
            public string LastLogin;
            public string PlayedTime;
        }
        public class CharactersTraits
        {
            public int CharacterId;
        }
        public class CharactersClothes
        {
            public int CharacterId;
            public string clothes;
        }
        public class User
        {
            public int Id;
        }
    }
    

    【讨论】:

    • 给猫剥皮的方法不止一种。
    • 谢谢,我设法使用 EF 上的导航属性做到了这一点。
    猜你喜欢
    • 1970-01-01
    • 2013-11-28
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    • 2017-11-07
    • 2014-10-07
    相关资源
    最近更新 更多