0

This is a follow-up of this question.

I am now working with ConcurrentDictionary, but while browsing through it, I am still launching the constructor of my Conn object, which is what I'm trying to avoid.

Source code:

public static ConcurrentDictionary<string, Conn> GetAllToDictionary(DbContext context)
{
    var result = new ConcurrentDictionary<string, Conn>();
    foreach (var conn in context.Set<Conn>().ToList())
        result.TryAdd(conn.Name, conn);
    return result;
}

Apparently, in the context.Set<Conn>().ToList(), the constructor of Conn gets called.

How can I avoid that? I just want to get the already existing Conn without re-creating one.

Edit: Conn constructor

My Conn constructor looks as follows:

public Conn(string name, IPAddress address, int port)
{
    Name = name;
    Address = address;
    Port = port;
    TcpConnection = new TcpConnection(Address, Port, 8192);
    Status = ConnectionStatus.NotConnected;
}
Dominique
  • 16,450
  • 15
  • 56
  • 112
  • I think one option could be to use `AsNoTracking()` before `ToList()` but it has side effects like disabling the change tracking and lazy loading – Vivek Nuna Jan 06 '23 at 12:54
  • 1
    You are still querying database with Entity Framework to get Conn, and create TcpConnection inside Conn constructor (I assume), exactly like in that question. You need to remove any custom code (especially creation of TcpConnection) from Conn constructor. Retrieve metadata from database and then create instance of TcpConnection and put it to the dictionary. – Evk Jan 06 '23 at 12:55
  • @Evk: You're right. I've added the `Conn` constructor. Are you saying I can't create the `TcpConnection` in there? If so, what do I need to do? – Dominique Jan 06 '23 at 12:58
  • You need to treat Conn as a database row, which it actually is. Database cannot store tcp connection, so do not create it inside Conn constructor. I don't know how are you using those classes so can't tell where exactly to create it though. If you only fetch all metadata on startup for example - then on startup get all Conn, then separately create TcpConnection for each of them and store them together in a dictionary (create another class which holds Conn and TcpConnection in separate properties). – Evk Jan 06 '23 at 13:02
  • 1
    Put the TcpConnection in a new class that represent the logic you need the TcpConnection for. And that class then can take a Conn object but itself isn't a Conn. – Ralf Jan 06 '23 at 13:04
  • 1
    Or maybe just let TcpConnection itself accept Conn object in constructor, it seems like it needs this metadata anyway. – Evk Jan 06 '23 at 13:06
  • @Evk: I am now working, next to the `Conn`, with a `ConnManager`, who does all the actual work and who also contains the `TcpConnection`, who, in his turn, contains the `Socket` objects. Like this, the `Conn` only serves as an interface to the database and the `ConnManager` does all the work. Result: the Entity Framework does not have the opportunity anymore to interfere with the `TcpConnection` objects nor the `Socket` objects and everything is working fine now. THANKS A LOT for your support, I would never have found it without you! – Dominique Jan 06 '23 at 14:10
  • What's the reason for returning a `ConcurrentDictionary`, instead of a simpler and more efficient `Dictionary`? – Theodor Zoulias Jan 06 '23 at 16:46

1 Answers1

1

What you want to do is get the address and port info from the database and then use it to build the connections.

Get rid of the constructor inside Conn and then change GetAllToDictionary to this:

public static ConcurrentDictionary<string, TcpConnection> GetAllToDictionary(DbContext context)
{
    var result = new ConcurrentDictionary<string, TcpConnection>();
    foreach (var conn in context.Set<Conn>().ToList())
        result.TryAdd(conn.Name, new TcpConnection(conn.Address, conn.Port, 8192););
    return result;
}

If the constructor inside Conn is referenced elsewhere and you cannot completely remove it, then just remove the line where you create the TcpConnection.

Evk
  • 98,527
  • 8
  • 141
  • 191
YungDeiza
  • 3,128
  • 1
  • 7
  • 32
  • As mentioned in my last comment to @Evk, I have created yet another object, referring to `TcpConnection`. This allows me to have two things: an interface to the database, the `Conn` object, queryable via Entity Framework, and the `ConnManager` object, responsible for the whole communication. This, together with the `ConcurrentDictionary` approach, makes the whole thing work. – Dominique Jan 06 '23 at 14:13