0

I am trying to rewrite and integrate the following code in to a single statement:

So instead of having to do this:

     var dbList = await _context.ProfileSections.Select(p => new
        {
            p.Id,
            p.Description,
            p.InformationText
        }).ToListAsync();

        var localisedList = dbList.Select(p => new
        {
            p.Id,
            Description = p.Description.Translate(),
            Information = p.InformationText.Translate()
        }).ToList();

I assume I could use if I strongly type to a model and use a foreach, something like:

 var dbList = await _context.ProfileSections.Select(p => new ProfileSectionModel
        {
            p.Id,
            p.Description,
            p.InformationText
        }).ToListAsync();

        var localisedList = dbList.ForEach(l => {
            l.Description = l.Description.Translate();
            l.InformationText = l.InformationText.Translate();
        }).ToList();

However then get error message: Operator '.' cannot be applied to operand of type 'void'

So is there an easier to combine the two statements? Or will I always have to as the first returns an anonymouse type. Unsure what is the correct way to handle this?

EDIT

Could use the following but was then getting issue with the dynamic proxies that EF uses. I guess thats why its selecting into an anonymous type?

    var dbList = await _context.ProfileSections.ToListAsync();

    foreach (var item in dbList)
    {
        item.Description = item.Description.Translate(),
        item.Information = item.InformationText.Translate()
    }
Paolo B
  • 3,026
  • 5
  • 21
  • 43
  • see new code in new answer – Wolfgang Jacques Apr 30 '19 at 14:12
  • "I am trying to rewrite and integrate the following code in to a single statement:" - I suppose conciseness has a place, but *why* exactly are you after a single statement here? These two statements do fundamentally different things - one *goes to a database* and the other simply does some mapping. Just because they have sort-of-the-same-shape doesn't mean they *have* to be stuck together. (btw, your title refers to "2 foreach statements" but I don't see any here...) – AakashM Apr 30 '19 at 14:24
  • `dbList` is of type `List`. `List.ForEach` isn't a function but a procedure - it returns no value, its purpose is to execute side-effects in the lambda. So you are modifying `dbList` in the `ForEach` just like you had a regular `foreach` loop - which would be a better way to go. `List.ForEach` is rarely a good idea. So `.ToList()` and `var x = ` makes no sense with `ForEach`. – NetMage Apr 30 '19 at 22:01

3 Answers3

0

Dont't use ForEach at all. You can do it in one go within the LINQ Select Statement. As for your error: I suppose it comes from dbList.ForEach which is not correct usage.

void Main()
{
    var listOne = new List<dings>{
        new dings() {id = 1, name = "aaa"},
        new dings() {id = 2, name = "bbb"},
        new dings() {id = 3, name = "ccc"},
    };

    var listTwo = listOne.Select(x => new bums() 
        {
            idbums = x.id + 33, 
            namebums = x.name + "hoho"
        }
    ).ToList();
}

public class dings{
    public int id;
    public string name;
}

public class bums
{
    public int idbums;
    public string namebums;
}
Wolfgang Jacques
  • 769
  • 6
  • 15
  • 1
    Then get error if I use Translate() method directly in `dbList` -- NotSupportedException: LINQ to Entities does not recognize the method 'System.String Translate(System.String)' method, and this method cannot be translated into a store expression – Paolo B Apr 30 '19 at 13:37
0

Use a Join like this :

    class Program
    {
        static void Main(string[] args)
        {
            DataBase _context = new DataBase();

            List<ProfileSections> localisedList = new List<ProfileSections>();

            var results = localisedList  
                           .Select(p => new
                           {
                               Id = p.Id,
                               Description = p.Description,
                               InformationText = p.InformationText,
                               TranslateDescription = p.TranslateDescription,
                               TranslateInformationText = p.TranslateInformationText
                           }).ToList();
        }
    }
    public class DataBase
    {
        public List<ProfileSections> ProfileSections { get; set; }
    }
    public class ProfileSections
    {
        public int Id { get; set; }
        public string Description { get; set; }
        public string InformationText { get; set; }

        public string TranslateInformationText
        {
            get { return TranslateFunction(InformationText); }
            set { ;}
        }

        public string TranslateDescription
        {
            get { return TranslateFunction(Description); }
            set { ;}
        }

        private string TranslateFunction(string s)
        {
            return s;
        }
    }
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • Apologise if unclear in example - `.Translate()` is method that is translating the Value for `Description` & `InformationText` thats held in Database. I basically just want to run this method on the results from `dbList` – Paolo B Apr 30 '19 at 13:18
  • I updated code but not sure if localisedList is the same type as the dbContext. You may want to look at this posting : https://stackoverflow.com/questions/20901419/how-to-call-stored-procedure-in-entity-framework-6-code-first – jdweng Apr 30 '19 at 13:29
0

Since your translate method does not work within the LINQ query, a foreach might indeed be useful. Try like that:

void Main()
{
    var listOne = new List<dings>{
        new dings() {id = 1, name = "aaa"},
        new dings() {id = 2, name = "bbb"},
        new dings() {id = 3, name = "ccc"},
    };

    var listTwo = new List<bums>();
    foreach (var item in listOne)
    {
        listTwo.Add(
        new bums()
            {
                idbums = item.id + 33,
                namebums = item.name + "hoho"
            }
        );
    }
}

public class dings
{
    public int id;
    public string name;
}

public class bums
{
    public int idbums;
    public string namebums;
}
Wolfgang Jacques
  • 769
  • 6
  • 15