Data-to-model filling with basic knowledge

Source: Internet
Author: User
Tags findone

Currently, in development, we usually query data from the database, and then fill the data into an object, so that we can easily read the object information. The process of filling data into objects is very cumbersome. to simplify this issue, various frameworks and components are emerging one after another. I cannot list them one by one -_-! Many frameworks are easy to use, but I always think of a sentence. The original text is vague and the source is forgotten.To a certain extent, technologies will fail in their respective ways.", Not to mention failure or failure, the Framework staff must have such feelings at a certain time:" if this framework supports XX, it would be nice. "and" this function was originally very simple, however, our project now uses this framework. To implement this function, we need to write fully qualified code. "and" this framework is becoming increasingly incompatible with our requirements, should we change to the YY framework?" And so on. Therefore, the framework has its own limitations. Do we need to turn to the framework for the first time if we are faced with problems?

What I want to express in this article is not to despise the framework, but there are a lot of discussions on the framework in the garden. It often gives new users a feeling that they are not familiar with the framework and don't use the framework, at the same time, it also makes many new users feel like they are awesome because they use many frameworks. In either case, it is not conducive to their technical improvement. Therefore, this article only hopes that new users can think deeply about their current situation, give them a correct assessment, and try to figure out how to implement it internally, to put it bluntlyI am familiar with the language and have an understanding of some ideas.In the following example, we will not list all types of frameworks. We will use a technology that all new users know to combine a data-to-object implementation.

Prerequisites and questions:

Prepare 1. Database test1 has table MyUser {

ID (PK, int, not null)

UserName (varchar (20), not null)

Age (tinyint, not null)

Birthday (datetime, null)

}

Prepare 2. Database test2 has table Message {

ID (PK, int, not null)

MyUserID (int, not null)

Content (nvarchar (200), not null)

AddTime (datetime, not null)

}

Prepare 3: SQLHelper. You can access the database without having to mention it!

Question 1: only one data-to-object filling is implemented once, no matter how many fields are retrieved, whether one data entry or multiple data entries

Question 2: associated queries. In order to emphasize the demonstration, the associated data is stored in different databases, specifically, the user and their messages are queried (it may be more appropriate to use dynamic and comments for example, thank you !)

Thoughts:

If you want to reuse it, you will naturally think of inheritance;

Abstract is also required for unified processing;

To dynamically add data, you must remember to think of dictionaries,A dictionary is a useful data structure.;

To get different types of objects in a unified way, it is natural to be generic.

The following figure shows them one by one. It doesn't matter if it's unclear.

Implementation:

Data to object filling, specific to ado.net, is generally reader to object, to achieve dynamic fields are filled with a method, in MyUser, probably like this:

public MessageInfo FillModelFromReader(DbDataReader reader, params string[] fields)        {            var info = new MessageInfo();            if (DALUtil.HasFields("ID", fields)) { info.ID = (int)reader["ID"]; }            if (DALUtil.HasFields("MyUserID", fields)) { info.MyUserID = (int)reader["MyUserID"]; }            if (DALUtil.HasFields("Content", fields)) { info.Content = reader["Content"].ToString(); }            if (DALUtil.HasFields("AddTime", fields)) { info.AddTime = (DateTime)reader["AddTime"]; }            return info;        }

There are only a few methods for database interaction. We can abstract a base class for data access and write several methods for overloading in actual use to facilitate calls.

/// <Summary> /// DAL base class /// </summary> /// <typeparam name = "T"> </typeparam> public abstract class DALBase <T >{/// <summary> /// the link used by the subclass. /// </summary> protected abstract string ConnName {get ;} protected abstract T FillModelFromReader (DbDataReader reader, params string [] fields); protected string GetConnStr () {return System. configuration. configurationManager. connectionStrings [ConnName]. connec TionString;} protected List <T> FindList (string SQL, CommandType type, params SqlParameter [] parameters) {using (var reader = SqlHelper. executeReader (GetConnStr (), type, SQL, parameters) {List <T> list = new List <T> (); var fields = DALUtil. getReaderFieldNames (reader); while (reader. read () {list. add (FillModelFromReader (reader, fields);} return list ;}} protected T FindOne (string SQL, Command Type type, params SqlParameter [] parameters) {return FindList (SQL, type, parameters ). firstOrDefault ();} private List <T> FindPage (string tableName, string fields, string query, string orderby, int pageIndex, int pageSize, bool isTotal, out int totalCount, params SqlParameter [] parameters) {if (pageIndex <1) {throw new ArgumentException ("pageIndex parameter> 1");} StringBuilder sb = new StringBuilder (); SqlParameter [] newPs; if (isTotal) {sb. AppendFormat ("select count (0) from [{0}]", tableName); if (! String. isNullOrWhiteSpace (query) {sb. appendFormat ("where {0}", query);} totalCount = GetCount (sb. toString (), parameters); sb. clear (); newPs = SqlHelper. copyParameters (parameters);} else {newPs = parameters; totalCount = 0;} if (string. isNullOrWhiteSpace (orderby) {throw new ArgumentException ("The orderby parameter should not be blank");} var fs = string. isNullOrWhiteSpace (fields )? "*": String. join (",", fields); sb. appendFormat ("select {0} from (", fs); sb. appendFormat ("select top {0} {1}, ROW_NUMBER () over (order by {2}) rowid from {3}", pageIndex * pageSize, fs, orderby, tableName); if (! String. isNullOrWhiteSpace (query) {sb. appendFormat ("where {0}", query);} sb. appendFormat (") t where t. rowid> {0} and t. rowid <= {1} ", (pageIndex-1) * pageSize, pageIndex * pageSize); return FindList (sb. toString (), CommandType. text, newPs);} protected object GetScalar (string SQL, CommandType type, params SqlParameter [] parameters) {return SqlHelper. executeScalar (GetConnStr (), type, SQL, parameters);} protected int GetCount (string SQL, CommandType type, params SqlParameter [] parameters) {var obj = GetScalar (SQL, type, parameters); if (obj = null) return-1; return (int) obj;} protected int Execute (string SQL, CommandType type, params SqlParameter [] parameters) {return SqlHelper. executeNonQuery (GetConnStr (), type, SQL, parameters );}}View Code

Implement MyUserDAL, inherit from DALBase <MyUserInfo>, set your own Link name, and implement your own filling method. All queries directly call the method of the base class, no matter which query, the filling method implemented by myself will be called in the base class! In this case, problem 1 is solved. (Both the model and FillModelFromReader use MyGeneration)

public class MyUserDAL : DALBase<MyUserInfo>    {        protected override string ConnName        {            get { return "sqlconn1"; }        }        protected override MyUserInfo FillModelFromReader(DbDataReader reader, params string[] fields)        {            var info = new MyUserInfo();            if (DALUtil.HasFields("ID", fields)) info.ID = (int)reader["ID"];            if (DALUtil.HasFields("UserName", fields)) info.UserName = reader["UserName"].ToString();            if (DALUtil.HasFields("Age", fields)) info.Age = (byte)reader["Age"];            if (DALUtil.HasFields("Birthday", fields) && !(reader["Birthday"] is DBNull)) info.Birthday = (DateTime)reader["Birthday"];            return info;        }        public MyUserInfo FindOne(int id)        {            var sql = "select * from MyUser where ID=@id";            return FindOne(sql, DALUtil.CreateParameter("id", id));        }        public List<MyUserInfo> Find1()        {            var sql = "select ID,UserName from MyUser";            return FindList(sql);        }        public List<MyUserInfo> Find2()        {            var sql = "select ID,UserName,Age,Birthday from MyUser";            return FindList(sql);        }    }

Question 2: Table association. In this case, we need to think of a dictionary. The dictionary is really hard to emphasize. For the UI Layer, we extract data from the model. Therefore, the associated data must also be in the model. We create a base class for the model that requires the associated data, associated data can be understood as a type of additional data, so we will call it additional data:

/// <Summary> // append the data base class to the model layer /// </summary> [Serializable] public class ModelBase {private Dictionary <string, object >_exdata = new Dictionary <string, object> (); public Dictionary <string, object> exData {get {return _ ExData ;}set {_ exData = value ;}} /// <summary> /// get the additional data /// </summary> /// <typeparam name = "T"> </typeparam> /// <param name = "name"> </param> // <returns> </returns> public T GetExData <T> (string name) {object data; if (_ exData. tryGetValue (name, out data) {return (T) data;} return default (T );} /// <summary> /// add additional data /// </summary> /// <param name = "name"> </param> /// <param name = "obj"> </param> public void AddExData (string name, object obj) {_ exData. add (name, obj );} /// <summary> /// check whether the attached data exists /// </summary> /// <param name = "name"> </param> // <returns> </returns> public bool ExistsExData (string name) {return _ exData. containsKey (name );}}

If MyUserInfo has additional data, let MyUserInfo inherit from ModelBase. After the inheritance, it will have the ability to store additional data. Where can this operation be written? Of course, it is written to BLL. First, the Message function is implemented. Here we need a public List <MessageInfo> FindByUserIDs (IEnumerable <int> userids) to get a set of MessageInfo based on a string of userids. The code is not pasted, And the download is attached below. Directly view the operations in MyUserBLL:

    public class MyUserBLL    {        DAL.MyUserDAL dal = new DAL.MyUserDAL();        public MyUserInfo FindOne(int id)        {            return dal.FindOne(id);        }        public List<MyUserInfo> Find1()        {            var list = dal.Find1();            return list;        }        public List<MyUserInfo> Find2()        {            var list = dal.Find2();            DealMsg(list);            return list;        }        static void DealMsg(List<MyUserInfo> list)        {            var ids = list.Select(u => u.ID);            MessageBLL msgbll = new MessageBLL();            var msgs = msgbll.FindByUserIDs(ids);            foreach (var info in list)            {                info.AddExData("Messages", msgs.Where(msg => msg.MyUserID == info.ID).ToList());            }        }    }

A DealMsg method is used to connect data from two databases. For example, the DealXX method can be used to add multiple data as needed. Then, let's take a look at the test:

    class Program    {        static MyUserBLL userbll = new MyUserBLL();        static void Main(string[] args)        {            F0();            Console.WriteLine();            F1();            Console.WriteLine();            F2();        }        static void F0()        {            var info = userbll.FindOne(2);            Console.WriteLine(info.ToString());        }        static void F1()        {            var list = userbll.Find1();            foreach (var info in list)            {                Console.WriteLine(info.ToString());            }        }        static void F2()        {            var list = userbll.Find2();            foreach (var info in list)            {                Console.WriteLine(info.ToString());                var messages = info.GetExData<List<MessageInfo>>("Messages");                foreach (var msg in messages)                {                    Console.WriteLine("\t{0}", msg.ToString());                }                Console.WriteLine();            }        }    }

Close now!

A lot of simple things are well mastered, and some events can be combined!

Download

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.