-1

The question is about conception.

I have simple class like this:

public class Data
{
    string Server = "";

    public Data(string Server)
    {
        this.Server = Server;
    }

    public class Items
    {
        public class Item
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }

        public Item Get(int Id)
        {
            var result = new Item();

            // here im am using sql connection to set result, but i need Server value in connnection string

            return result;
        }
    }        
}

It may not make sense but I explain what I want to achieve.
Right now i can make instance like this:

var data = new Data("0.0.0.0");
var item = new Data.Items().Get(3);

But the objects are not connected in any way.
And I would like to get/set data in this way:

var item = new Data("0.0.0.0").Items().Get(3);

or like this:

var data = new Data("0.0.0.0");
var item1 = data.Items().Get(3);
var item2 = data.Items().Save(3);
var item3 = data.OtherItems().Get(3);

In short, I would like to initiate the main class and pass a parameter that is required to execute methods in subclasses. Using methods in subclasses should not be possible if they are not called from the parent class.
Is it possible?

The goal is to determine once from which database instance the data come from without using static prop. And then calling individual methods without having to pass the name of the SQL instance.

Edit for a deeper explanation:

Right now i can write all the methods in main class like this.

public class Data
{
    string Server = "";

    public Data(string Server)
    {
         this.Server = Server;
    }

    public List<Item> Items_List() { return new List<Item>(); }
    public Item Items_Get(Int32 id) { return new Item(); }
    public void Items_Save(Item item) { }

    public List<Firm> Firms_List() { return new List<Firm>(); }
    public Firm Firms_Get(Int32 id) { return new Firm(); }
    public void Firms_Save(Firm item) { }

    public List<Location> Location_List() { return new List<Location>(); }
    public Location Location_Get(Int32 id) { return new Location(); }
    public void Location_Save(Location item) { }
}

Then i call like this:

var firms = data.Firms_List();
var firm = data.Firms_Get(firms[0].Id);
firm.Name = "New name";
data.Firms_Save(firm);

I want to change "_" to "." in method name for better visibility and for type grouping like this:

var firms = data.Firms.List();
var firm = data.Firms.Get(firms[0].Id);
firm.Name = "New name";
data.Firms.Save(firm);

Is this possible?
Maybe there is a way for grouping methods like above?
Or maybe idea is wrong.

Dominik
  • 209
  • 2
  • 13
  • 1
    Your first example does not compile. – FCin Feb 27 '18 at 16:24
  • Maybe it's just too early for me here, but you should be seeing plenty of obvious compile-time errors, no? Some of the code you say you can do does not seem like it should be compiling at all. – Broots Waymb Feb 27 '18 at 16:27
  • public class Data is in separate .cs and compiled fine. Of course code below "And I would like to get/set data in this way:" don't work. It is only example how the calling should look like. – Dominik Feb 27 '18 at 17:53

5 Answers5

1

Your Data object can hold the server (and other related information like credentials) but your member objects for each type must have a reference to the Data object in order to access the correct instance data:

public class Data {
    string server;
    public Data(string Server) {
        server = Server;

        items = new DataBase<Item>(this);
        firms = new DataBase<Firm>(this);
        locations = new DataBase<Location>(this);
        otherItems = new OtherItem(this);
    }

    public class DataBase<T> where T : new() {
        Data data;
        public DataBase(Data myData) {
            data = myData;
        }

        public virtual List<T> List() => new List<T>();
        public virtual T Get(Int32 id) => new T();
        public virtual void Save(T item) {
            var s = data.server;
        }
    }

    public class OtherItem : DataBase<Item> {
        public OtherItem(Data myData) : base(myData) {
        }
        public override List<Item> List() {
            return new List<Item>();
        }
        public override Item Get(int id) {
            return new Item();
        }
        public override void Save(Item item) {
            base.Save(item);
        }
    }

    DataBase<Item> items;
    DataBase<Firm> firms;
    DataBase<Location> locations;
    OtherItem otherItems;

    public DataBase<Item> Items() => items;
    public DataBase<Firm> Firms() => firms;
    public DataBase<Location> Locations() => locations;
    public OtherItem OtherItems() => otherItems;
}

Now you can do this:

var data = new Data("0.0.0.0");
var item1 = data.Items().Get(3);
data.Items().Save(item1);
var item3 = data.OtherItems().Get(3);

I wouldn't bother with the method Items() and just use an Item property directly instead.

I don't see how you can prevent someone from storing a sub-reference and using it, however:

var dataItems = data.Items();
var item4 = dataItems.Get(4);
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • Thank you for your answer! This answer is closest to what I wanted to get and I will use it for now. – Dominik Feb 27 '18 at 21:38
0

It looks like you need a kind of repository class which acts on an item table.

public class Items
{
    private Server { get; }
    public Items(string server) => Server = server;
    public Item Get(int id)
    {
        var item = new Item();
        //use Server inside the connectionString
        return item;
    }
    public void Save(Item item)
    {
        //use server inside the connectionstring to save the given item
    }
}
Spotted
  • 4,021
  • 17
  • 33
0

Very strange design. I would think you just need the Item class ... and inside that class is the access to an sql database via f.e. a connection string or a global connection that's been opened earlier. The connection string can be stored in web.config or app.config, and used everywhere in your application.

Update:

Would below work for you ? ... I tried it in a Windows Forms app, and this statement works there :

Item myItem = new Data("0.0.0").Item_Get (1);

Class :

public class Data {
    string Server = "";

    public Data(string Server) {
        this.Server = Server;
    }

    public Item Item_Get(int Id) {
        var result = new Item();

        // here im am using sql connection to set result, but i need Server value in connnection string

        return result;
    }
}

public class Item {
    public int Id { get; set; }
    public string Name { get; set; }
}
kahoona
  • 175
  • 2
  • 14
  • It is not strange. I am trying to do this, because the code is compiled to DLL. So the call should be simple as possible, by creating one object (passing string with SQL instance) and then calling only methods. There are more that one class like Items, that i need to access like this. I am trying to find solution, where passing parameter is obligatory and should be done only once. – Dominik Feb 27 '18 at 18:58
  • Please check my edit. I can do it like this, but for me it is not nice solution, when i am trying to do this with more that one class. – Dominik Feb 27 '18 at 19:36
-1

I'm not sure that I understand what is the purpose of this design, but anyway, you could think of some syntactically correct ways to implement that.

For one thing, you can make a method abstract. In that case, only the implementation from the derived class could ever be executed. If this method is protected, then only the parent class can invoke it.

On the other hand, despite your explanation that you don't want "pass the name of the SQL instance", my impression is that object state is precisely meant for that purpose - to make a distinction between objects with different history, and therefore make them behave differently.

I don't know if this satisfies your expectations, but again - I am very concerned about the motivations behind the design you're proposing.

Zoran Horvat
  • 10,924
  • 3
  • 31
  • 43
  • I understand your concern. I edited my question for better explanation. Please check it. In the meantime ill try suggestion with abstract method. – Dominik Feb 27 '18 at 19:33
-1

can achieve by using fluent interface.

A fluent interface is a specialized, self-referencing form of method chaining where the context is maintained through the chain.

have reference on this stackoverflow Q&A

Arunraja A
  • 174
  • 5