How should I pass data between classes and application layers?

后端 未结 8 1696
太阳男子
太阳男子 2021-01-30 07:16

For example, if I am creating a 3 layer application (data / business / UI) and the data layer is grabbing single or multiple records. Do I convert everything from data layer in

相关标签:
8条回答
  • 2021-01-30 07:43

    The application that I'm working on now is fairly old (in .NET terms) and uses strongly typed datasets to pass data between the data layer and the business layer. In the business layer, the data in the datasets is manually "or mapped" to business objects before being passed to the front end.

    This is probably not a popular design decision though because strongly typed dataset were always somewhat controversial.

    0 讨论(0)
  • 2021-01-30 07:44

    I strongly suggest that you do it with objects. Some other way suggests that only interfaces are publics while your implementations are internal, and you expose your methods through a factory of your object, then couple your factories with a façade to finally have a single and unique entry point to your library. Then, only data objects goes through your façade, so you always know what to expect inside as outside your façade.

    This way, any UI could call your library's façade, and the only thing that would remain to code is your UI.

    Here's a link which I find personally very interesting that explains in summary the different design patterns: GoF .NET Design Patterns for C# and VBNET.

    If you'd rather a code sample illustrating what I'm stating, please feel free to ask.

    0 讨论(0)
  • 2021-01-30 07:48

    Whatever means you use to pass data between the layers of your application, just be sure that the implementation details of each layer do not leak into the others. You should be able to change how the data in the relational database is stored without modifying any of the code in the business objects layers (other than serialization of course).

    A tight coupling between the design of the business objects and the relational data model is extremely irritating and is a waste of a good RDBMS.

    0 讨论(0)
  • 2021-01-30 07:50

    I´d add a new layer, ORM Object Relational Mapping, with the responsability to transform data from Data layer into bussiness objects collections. I think that using objects in your bussiness model is the best practice.

    0 讨论(0)
  • 2021-01-30 07:51

    There are nearly as many "correct" ways to do this as there are programming teams in the world. That said, what I like to do is build a factory for each of my business objects that looks something like this:

    public static class SomeBusinessObjectFactory
    {
       public static SomeBusinessObject FromDataRow(IDataRecord row)
       {
           return new SomeBusinessObject() { Property1 = row["Property1"], Property2 = row["Property2"] ... };
       }
    }
    

    I also have a generic translation method that I use to call these factories:

    public static IEnumerable<T> TranslateQuery(IEnumerable<IDatarecord> source, Func<IDatarecord, T> Factory)
    {
        foreach (IDatarecord item in source)
            yield return Factory(item);
    }
    

    Depending on what your team prefers, the size of the project, etc, these factory objects and translator can live with the business layer or data layer, or even an extra "translation" assembly/layer.

    Then my data layer will have code that looks like this:

    private SqlConnection GetConnection()
    {
        var conn = new SqlConnection( /* connection string loaded from config file */ );
        conn.Open();
        return conn;
    }
    
    private static IEnumerable<IDataRecord> ExecuteEnumerable(this SqlCommand command)
    {
        using (var rdr = command.ExecuteReader())
        { 
            while (rdr.Read())
            {
                yield return rdr;
            }
        }
    }
    
    public  IEnumerable<IDataRecord> SomeQuery(int SomeParameter)
    {
        string sql = " .... ";
    
        using (var cn = GetConnection())
        using (var cmd = new SqlCommand(sql, cn))
        {
            cmd.Parameters.Add("@Someparameter", SqlDbType.Int).Value = SomeParameter;
            return cmd.ExecuteEnumerable();
        }
    }
    

    And then I can put it all together like this:

     SomeGridControl.DataSource = TranslateQuery(SomeQuery(5), SomeBusinessObjectFactory.FromDataRow);
    
    0 讨论(0)
  • 2021-01-30 07:53

    In general, I think it is better to send objects rather than data tables. With objects, each layer knows what it is receiving (which objects with what properties etc.). You get compile time safety with objects, you can't accidentally misspell a property name etc. and it forces an inherent contract between the two tiers.

    Joshua also brings up a good point, by using your custom object, you are also decoupling the other tiers from the data tier. You can always populate your custom object from another data source and the other tiers will be none the wiser. With a SQL data table, this will probably not be so easy.

    Joel also made a good point. Having your data layer aware of your business objects is not a good idea for the same reason as making your business and UI layers aware of the specifics of your data layer.

    0 讨论(0)
提交回复
热议问题