0

So I have a .txt file with the following entities

1,1,10,PARTICIPANT
2,1,15,PARTICIPANT
3,1,8,PARTICIPANT
4,1,20,PARTICIPANT
5,1,30,PARTICIPANT
6,1,7,REZERVA
7,1,5,PARTICIPANT
8,1,14,PARTICIPANT
9,1,4,PARTICIPANT
10,1,11,PARTICIPANT
11,1,10,REZERVA
12,1,6,PARTICIPANT
13,2,15,REZERVA
14,2,25,PARTICIPANT
15,2,10,PARTICIPANT
16,2,6,PARTICIPANT
17,2,40,PARTICIPANT
18,2,18,PARTICIPANT
19,2,7,PARTICIPANT
20,2,17,REZERVA
21,2,24,PARTICIPANT
22,2,15,PARTICIPANT
23,2,10,PARTICIPANT
24,2,11,PARTICIPANT
1,3,11,PARTICIPANT
2,3,12,PARTICIPANT
3,3,6,REZERVA
4,3,13,PARTICIPANT
5,3,14,PARTICIPANT
6,3,17,PARTICIPANT
19,3,11,PARTICIPANT
20,3,8,REZERVA
21,3,11,PARTICIPANT
22,3,12,PARTICIPANT
23,3,14,PARTICIPANT
24,3,15,PARTICIPANT
7,4,0,REZERVA
8,4,20,PARTICIPANT
9,4,21,PARTICIPANT
10,4,13,PARTICIPANT
11,4,9,PARTICIPANT
12,4,14,PARTICIPANT
13,4,30,PARTICIPANT
14,4,25,PARTICIPANT
15,4,15,PARTICIPANT
16,4,44,PARTICIPANT
17,4,12,REZERVA
18,4,8,PARTICIPANT
1,5,14,PARTICIPANT
2,5,8,PARTICIPANT
3,5,8,PARTICIPANT
4,5,8,REZERVA
5,5,18,PARTICIPANT
6,5,28,PARTICIPANT
13,5,40,PARTICIPANT
14,5,20,REZERVA
15,5,15,PARTICIPANT
16,5,8,PARTICIPANT
17,5,8,PARTICIPANT
18,5,12,PARTICIPANT
19,6,10,PARTICIPANT
20,6,20,PARTICIPANT
21,6,20,PARTICIPANT
22,6,15,PARTICIPANT
23,6,15,PARTICIPANT
24,6,16,REZERVA
7,6,28,PARTICIPANT
8,6,10,PARTICIPANT
9,6,28,PARTICIPANT
10,6,10,REZERVA
11,6,15,PARTICIPANT
12,6,5,PARTICIPANT

In my Model folder i have a Validator folder and 3 other clases:

Entity.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ex.Model
{
    public class Entity<TID>
    {
        public TID ID { get; set; }

    }
}

JucatorActiv.cs where i describe the JucatorActiv entity

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ex.Model
{
    enum Status { REZERVA, PARTICIPANT }
    class JucatorActiv : Entity<String>
    {
        public String IdMeci { get; set; }

        public Double NrPuncteInscrise { get; set; }

        public Status Tip { get; set; }

        public override string ToString()
        {
            return ID + " " + IdMeci + " " + NrPuncteInscrise + " " + Tip;
        }
    }
}

And JucatorActivToFile.cs where i transform the string into an JucatorActiv entity

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ex.Model
{
    class JucatorActivToFile
    {
        public static JucatorActiv CreateJucatorA(string line)
        {
            string[] fields = line.Split(',');
            // new char[] { ',' }     
            JucatorActiv jucA = new JucatorActiv()
            {
                ID = fields[0],
                IdMeci = fields[1],
                NrPuncteInscrise = Double.Parse(fields[2]),
                Tip = (Status)Enum.Parse(typeof(Status), fields[3])
            };
            return jucA;
        }
    }


}

After in my Repo folder i have:

A DataReader

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Ex.Repo
{
    class DataReader
    {
        public static List<T> ReadData<T>(string fileName, CreateEntity<T> createEntity)
        {
            List<T> list = new List<T>();
            using (StreamReader sr = new StreamReader(fileName))
            {
                string s;
                while ((s = sr.ReadLine()) != null)
                {
                    T entity = createEntity(s);
                    list.Add(entity);
                }
            }
            return list;
        }
    }
}

A repo interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ex.Model;

namespace Ex.Repo
{
    interface IRepo<ID, E> where E : Entity<ID>
    {
        IEnumerable<E> FindAll();

        E Save(E entity);

    }
}

A InMemoryRepo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ex.Model;
using Ex.Model.Validator;

namespace Ex.Repo
{
    class InMemoryRepo<ID, E> : IRepo<ID, E> where E : Entity<ID>
    {

        protected IValidator<E> validator;
        protected IDictionary<ID, E> entities = new Dictionary<ID, E>();

        public InMemoryRepo(IValidator<E> validator)
        {
            this.validator = validator;
        }

        public IEnumerable<E> FindAll()
        {
            return entities.Values.ToList<E>();
        }

        public E Save(E entity)
        {
            if (entity == null)
                throw new ArgumentNullException("Entity cannot be null!");
            if (this.entities.ContainsKey(entity.ID))
                return entity;
            else
                this.entities[entity.ID] = entity;
            return default;

        }
    }
}

A InFileRepo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ex.Model;
using Ex.Model.Validator;

namespace Ex.Repo
{
    public delegate E CreateEntity<E>(String record);



    abstract class InFileRepo<ID, E> : InMemoryRepo<ID, E> where E : Entity<ID>
    {
        protected String filename;

        protected CreateEntity<E> CreateEntity;

        public InFileRepo(IValidator<E> validator, String filename, CreateEntity<E> createEntity) : base(validator)
        {

            this.filename = filename;
            this.CreateEntity = createEntity;
            if (createEntity != null)
                loadFromFile();
        }

        protected virtual void loadFromFile()
        {
            List<E> list = DataReader.ReadData(filename, CreateEntity);
            list.ForEach(x => entities[x.ID] = x);
        }
    }
}

And a JucatorActivInFileRepo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ex.Model;
using Ex.Model.Validator;

namespace Ex.Repo
{
    class JucatorActivInFileRepo : InFileRepo<string, JucatorActiv>
    {
        public JucatorActivInFileRepo(IValidator<JucatorActiv> vali, string fileName) : base(vali, fileName, JucatorActivToFile.CreateJucatorA)
        {

        }
    }
}

In my Service class i have the followings:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ex.Model;
using Ex.Repo;

namespace Ex.Service
{
    class ServiceJucatori
    {
        private IRepo<String, JucatorActiv> repoJucatoriActivi;

        public ServiceJucatori(IRepo<String, JucatorActiv> repoJucatoriActivi)
        {
            this.repoJucatoriActivi = repoJucatoriActivi;
        }

        public List<JucatorActiv> FindAllJA()
        {
            return repoJucatoriActivi.FindAll().ToList();
        }

    }
}

In App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key ="jucatorActivFileName" value ="..\\..\\..\\Data\\jucatoriActivi.txt"/>
  </appSettings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
  </startup>
</configuration>

And finally in my Program i have:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ex.Model;
using Ex.Model.Validator;
using Ex.Repo;
using Ex.Service;
using System.Configuration;

namespace Ex
{
    class Program
    {
        static void Main(string[] args)
        {
            String jucatorActivFileName = ConfigurationManager.AppSettings["jucatorActivFileName"];

            IValidator<JucatorActiv> valJA = new JucatoriActiviValidator();

            IRepo<String, JucatorActiv> repoJA = new JucatorActivInFileRepo(valJA, jucatorActivFileName);

            ServiceJucatori serv = new ServiceJucatori(repoJA);

            foreach (JucatorActiv jA in serv.FindAllJA())
                Console.WriteLine(jA);
        }
    }
}

After I run Program.cs the output is the following:

 1 5 14 PARTICIPANT
2 5 8 PARTICIPANT
3 5 8 PARTICIPANT
4 5 8 REZERVA
5 5 18 PARTICIPANT
6 5 28 PARTICIPANT
7 6 28 PARTICIPANT
8 6 10 PARTICIPANT
9 6 28 PARTICIPANT
10 6 10 REZERVA
11 6 15 PARTICIPANT
12 6 5 PARTICIPANT
13 5 40 PARTICIPANT
14 5 20 REZERVA
15 5 15 PARTICIPANT
16 5 8 PARTICIPANT
17 5 8 PARTICIPANT
18 5 12 PARTICIPANT
19 6 10 PARTICIPANT
20 6 20 PARTICIPANT
21 6 20 PARTICIPANT
22 6 15 PARTICIPANT
23 6 15 PARTICIPANT
24 6 16 REZERVA
Luke
  • 7
  • 3
  • 2
    You've given us a set of *fragments* of a program and somehow expect us to put together something similar enough to your program to reproduce the issue you're seeing. But there's no guarantee that you're showing us the *relevant* fragments. For instance, we're not seeing at all *how* the file is processed to populate the dictionary. Please try to create a [mcve] – Damien_The_Unbeliever Dec 14 '20 at 11:02
  • I didn't put what are you asking for because it's working for other files where i dont have multiple entities with the same id so i thought that i need to do smth different in this case. If you want me to put the rest of the code i will do it. – Luke Dec 14 '20 at 11:10
  • I put in some more, if you need anything else just tell me – Luke Dec 14 '20 at 11:17
  • I'd like for you to have *read* the help documentation I linked to. – Damien_The_Unbeliever Dec 14 '20 at 11:18
  • I did and create a new project just for this entity and it's working but i get the same output – Luke Dec 14 '20 at 11:45
  • There is a dissonance between the technical skills, architecture and implementations on display in the posted code, and not knowing that a dictionary expects unique keys. It feels like you're posting code where you don't quite know what it does but assume it has to be related to the problem you're experiencing - which is pointless bloat. My suggestion here is for you to read up on what a dictionary does and how it works, and if that doesn't answer your question, produce a [minimal example](https://stackoverflow.com/help/minimal-reproducible-example) that showcases the "issue" as you see it. – Flater Dec 14 '20 at 15:39
  • I have a bigger program where i have another entities, but when i read them from a file they have unique id's so i don't encounter the problem for them so that's why i used a dictionary. I am asking for help bcs i dont know what collection should i use in order to save all the entities from the file even if they have the same id. I understand that i need a 1:n mapping not a 1:1 but i don't know how to do it. – Luke Dec 14 '20 at 15:47

1 Answers1

0

This is a guess, but I think your code boils down to

var myDictionary = new Dictionary<int, int>();
myDictionary[0] = 1;
myDictionary[0] = 2;
myDictionary.ForEach(kvp => Console.WriteLine($"{kvp.Key} : {kvp.Value}");

And you are wondering why you get "0:2" instead of "0:1 0:2".

And the reason is that dictionary is a 1:1 mapping. If you want to keep all values you need a 1:n mapping, i.e. a Dictionary<int, List<T>, sometimes called a MultiValuedictionary. Microsoft have a implementation in Experimental collections.

If you want all values in a multi value dictionary you can use SelectMany, assuming .Values is IEnumerable<IEnumerable<T>>:

 myDictionary.Values.SelectMany(v => v); // IEnumerable<T>
JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Yes, that is exactly what i want to do but i dont know how. I know i need to have a new entitiesJA dictionary in repo, and i need to change the saving of data in loadFromFile but after i dont know how to change the repo and service findAll function so i could print them all. – Luke Dec 14 '20 at 14:06
  • @Luke Added some info about SelectMany. – JonasH Dec 14 '20 at 14:49
  • Oh, nice thank you. So instead of entities.Values.ToList() from InMemoryRepo is should use entittiesJ.Values.SelectMany(x=>x), right? And i have one more question. In my load from file i save the entities from file in my IDictionary like this list.ForEach(x => entities[x.ID] = x);. How should i do it for protected IDictionary> entitiesJ = new Dictionary>();? – Luke Dec 14 '20 at 15:11
  • @luke If you use the dictionary from Microsoft you would just call `entities.Add(x.ID, x)`. Just like you would for a normal dictionary. If you used that method with a normal dictionary the dictionary would even have told you about the bug you have by throwing an exception. – JonasH Dec 14 '20 at 15:25
  • When i enter this `list.ForEach(x => entitiesJ.Add(x.ID,x));` in loadFromFile function i get this error: CS1503 Argument 2: cannot convert from 'E' to 'System.Collections.Generic.List' – Luke Dec 14 '20 at 15:38
  • @Luke: _"i dont know how to change the repo and service"_ It seems your problems are more a lack of general skill and experience. You should talk to your team lead/tech lead on getting the support you need, as it seems you're not in the right position to independently develop changes to the codebase. That is not meant to offend, we were all in that position once. But don't try to get random internet strangers to explain your job for you. You don't learn that way, and will not improve. – Flater Dec 14 '20 at 15:45
  • it is not for my job i am a student and i just started to code in this program language so this is why i don't know so much about it. i just wanted to find out how can i have 1:n mapping and i am glad you told me about the > and i just wanted to find out if you knew how can i modify the loadFromfile function. – Luke Dec 14 '20 at 15:55
  • @Luke `.ForEach` is just a linq variant of a `foreach` loop, but it is not in the base framework. I just used it to keep the example short. See MoreLinq for an implementation: https://github.com/morelinq/MoreLINQ – JonasH Dec 14 '20 at 16:31
  • @JonasH I figured the loadFromFile problem out. Thank you for opening my eyes with the > stuff and for your patience with my inexperienced ass :)), i appreciate it!! Have a nice day! – Luke Dec 14 '20 at 16:39