简体   繁体   中英

Get First and Last element of a Collection at the same time

I'm currently working on a cross platform Project.

I'm facing the problem when trying to map the model between WebDataLayer.Models and Shared.Models.

namespace WebDataLayer.Models
{
    public class Factory
    {
        public Guid Id { get; set; }
        public string Name { get; set; }

        public string Serie { get; set; }

        public Guid? AreaId { get; set; }

        public virtual ICollection<FactoryHotline> FactoryHotlines { get; set; }
}

public class FactoryHotline
    {
        public Guid Id { get; set; }
        public Guid FactoryId { get; set; }

        [Required]
        [MaxLength(256)]
        public string Caption { get; set; }

        [Required]
        [MaxLength(256)]
        public string Hotline { get; set; }
    }

This is model in Shared:

namespace Shared.Models
{
    [DataContract]
    public class Factory
    {
        [DataMember(Name = "id")]
        public Guid Id { get; set; }

        [DataMember(Name = "areaId")]
        public Guid AreaId { get; set; }

        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "serie")]
        public string Serie { get; set; }

        [DataMember(Name = "hotLine1")]
        public FactoryHotline Hotline1 { get; set; }

        [DataMember(Name = "hotLine2")]
        public FactoryHotline Hotline2 { get; set; }
    }

public class FactoryHotline
    {
        [DataMember(IsRequired = true, Name = "Id")]
        public Guid Id { get; set; }

        [DataMember(Name = "FactoryId")]
        public Guid FactoryId { get; set; }

        [DataMember(Name = "Caption")]
        public string Caption { get; set; }

        [DataMember(Name = "Hotline")]
        public string Hotline { get; set; }
    }
}

This is code in Controller where I try to convert WebDatalayer.Models.Factory to Shared.Models.Factory :

public ActionResult Edit()
        {
            var factories = _factoryService.All().OrderBy(p => p.Name);
            List<Shared.Models.Factory> response = new List<Shared.Models.Factory>();

            response =  factories.Select(k => new Shared.Models.Factory
             {
                 Id = k.Id,
                 Name = k.Name,
                 Serie = k.Serie,
                 Hotline1 = new Shared.Models.FactoryHotline {
                     Id = k.FactoryHotlines.FirstOrDefault().Id,
                     Caption = k.FactoryHotlines.FirstOrDefault().Caption,
                     Hotline = k.FactoryHotlines.FirstOrDefault().Hotline,
                     FactoryId = k.FactoryHotlines.FirstOrDefault().FactoryId
                 },
                 Hotline2 = new Shared.Models.FactoryHotline
                 {
                     Id = k.FactoryHotlines.LastOrDefault().Id,
                     Caption = k.FactoryHotlines.LastOrDefault().Caption,
                     Hotline = k.FactoryHotlines.LastOrDefault().Hotline,
                     FactoryId = k.FactoryHotlines.LastOrDefault().FactoryId
                 },
            }).OrderBy(f => f.Name).ToList();
            return View("Edit", response);
        }

But linq to entities does not recognize the method lastordefault , cannot use order descending because I also get First element at the same time.

Need help!

You look like you want to return all factories ordered by name, and for each factory, return the first and last hotline:

var query = factories.Select(f => new Shared.Models.Factory
    {
        Id = f.Id, 
        Name = f.Name,
        Serie = f.Serie,
        Hotline1 = f.FactoryHotLines
            .OrderBy(h => h.Id)
            .Select(h => new Shared.Models.FactoryHotline 
            {
                Id = h.Id,
                Caption = h.Caption,
                Hotline = h.Hotline,
                FactoryId = h.FactoryId
            }).FirstOrDefault(),
        Hotline2 = x.FactoryHotLines
            .OrderByDescending(h => h.Id)
            .Select(h => new Shared.Models.FactoryHotline 
            {
                Id = h.Id,
                Caption = h.Caption,
                Hotline = h.Hotline,
                FactoryId = h.FactoryId
            }).FirstOrDefault(),
     }).OrderBy(f => f.Name)
     .ToList();

Key thing here: When using FirstOrDefault() , always provide an OrderBy clause. Rather than relying on FirstOrDefault() to get each individual value, use it with the OrderBy() to get the entity then use Select() to reduce it down to the desired view model.

The above example assumes you want the order they were added. (ID for identity-based records) This way we do the OrderBy() to get the first hotline, then an OrderByDescending() to get the second.

I'm not sure if this is the cleanest solution, but you could chain .Where like this:

.Where((v, i) => { return i == 0 || i == list.Count() -1; })

So..

factories = factories.Where((v, i) => { return i == 0 || i == factories.Count() -1; })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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