Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I breaking the DI pattern rules

I'm very new to DI so my knowledge isn't the greatest. I am currently working on a Asp.Net Core MVC application.

Suppose I have a DLL which returns a DataSet (I have full control over this DLL and can change it as required).

So the code in the DLL looks like:

public class DataStore : IDataStore
{       
   private readonly IConfiguration _configuration;       

   public DataStore(IConfiguration configuration)
   {
       _configuration = configuration;
   }

   public DataSet GetDataBySP(string spName, SqlParameter[] parameters = null)
   {
      DataSet ds = new DataSet();
      using(var con = new SqlConnection(_configuration.GetConnectionString("conStr")))
      {
         using(var cmd = new SqlCommand(spName, con))
         {
              cmd.CommandType = CommandType.StoredProcedure;

              if (parameters?.Length > 0)
                 cmd.Parameters.AddRange(parameters);

              con.Open();

              using (var da = new SqlDataAdapter(cmd))
              {
                 da.Fill(ds);
              }
         }
      }
      return ds;
   }
}

Now assuming I have a class named Foo which only contains two properties as follows:

public interface IFoo
{
   Foo GetFooData();
}

public class Foo : IFoo
{
    private readonly IDataStore _dataStore;

    public int CurrentCount { get; set; }
    public int MaxCount { get; set; }

    public Foo(DataRow dr)
    {
        CurrentCount = dr.Field<int>("CurrentCount");
        MaxCount = dr.Field<int>("MaxCount");
    }

    public Foo(IDataStore dataStore)
    {
        _dataStore = dataStore;
    }
}

In Foo I have a method called GetFooData as follows:

public Foo GetFooData()
{
    var ds = _dataStore.GetDataBySP("sp name");

    //is the below code breaking the DI pattern rule?
    return ds.Tables[0].AsEnumberable().Select(f => new Foo(f)).FirstOrDefault();
}

In the Startup.cs inside ConfigureServices(IServiceCollection services) method I do the following:

services.AddScoped<IFoo, Foo>();

So my question is, by doing new Foo(f) inside the Select() am I breaking the DI pattern? If yes, can you advice on how to overcome this please.

like image 462
Izzy Avatar asked Dec 03 '18 09:12

Izzy


People also ask

What happens if you break the pattern day trader rule?

If your account value falls below $25,000, then any pattern day trader activities may constitute a violation. If you trade futures, keep in mind that futures cash or positions do not count towards the $25,000 minimum account value. Getting dinged for breaking the pattern day trader rule is no fun.

What are the rules of pattern trading?

There are a few simple but strict rules that define pattern day trading. Let’s go over them. A “round trip” simply means opening and closing a security position. Whether you buy or sell to open, when you close the position, you’ve completed a round trip.

Are You a pattern day trader?

You are a pattern day trader if you make more than four day trades (as described above) in a rolling five business day period, and those trades make up more than 6% of your account activity within those five days. Self-identified day traders .


1 Answers

I would have solved your problem through usage of repositories and data transfer objects (DTO), like this:

Some public interfaces which you would be able to inject into your code:

    public interface IFooRepository
    {
        FooDto GetFirst();
    }

    public interface IDataSetFactory
    {
        DataSet GetDataSet(string spName, SqlParameter[] = null);
    }

Some DTO to pass data from one class to another (and only data):

    public class FooDto
    {
        public int CurrentCount { get; set; }
        public int MaxCount { get; set; }
    }

Some internal implementation, which hidden from eye of interface user:

    internal sealed class FooRepository : IFooRepository
    {
        private readonly IDataSetFactory _dsFactory;
        public FooRepository(IDataSetFactory dsFactory)
        {
            _dsFactory = dsFactory;
        }

        public FooDto GetFirst()
        {
            return _dsFactory.GetDataSet("sp name")
                             .Tables[0]
                             .AsEnumberable()
                             .Select(Map)
                             .FirstOrDefault();
        }
        private FooDto Map(DataRow dr)
        {
            return new FooDto
                   {
                       CurrentCount = dr.Field<int>("CurrentCount"),
                       MaxCount = dr.Field<int>("MaxCount")
                   };
        }
    }

    internal sealed class DataSetFactory : IDataSetFactory
    {
        public DataSetFactory() { }
        private DataSet GetDataSet(string spName, SqlParameter[] = null)
        {
            //set up sql parameters, open connection
            return ds;
        }
    }

And given some specific DI framework (Ninject, DryIoc, etc), you can inject those interfaces to any place in the code. The great benefit of using DI - it forces you to design your application correctly (interfaces separated from implementation), so at some point in time you can implement your IFooRepository to read data from stars in the sky, or from file, or to return empty results in testing, or whatever you desire it to do.

If you design incorrectly - it probably will not compile, or will be overcomplexed. Good usage of DI is hard question, but estimate is that 99% of your *.cs files will NOT reference ANY DI framework references:

using System.IO;
using Ninject; //<-- I mean, this one. If it is everywhere, something is overcomplexed and you are not using framework correctly.
using System.Media;
like image 93
eocron Avatar answered Sep 21 '22 12:09

eocron