使用C# 进行相对安全的数据库访问

使用C# 进行相对安全的数据库访问

基本的数据库访问

先看看基本的数据库访问,直接上代码,都已经做了注解

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace ReportOrders
{
    class Peport
    {
        
        static void Main(string[] args)
        {
            SqlConnection dataConnection = new SqlConnection();//新建一个数据库的连接
            try
            {
                SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();//构建一个连接SQL的字符串
                builder.DataSource = ".\\SQLExpress";//sqlServer实例名称
                builder.InitialCatalog = "Northwind";//使用的数据库名称
                builder.IntegratedSecurity = true;//使用windows验证
                /*
                 * 使用账号密码验证,也可自行百度 
                 * 不要在程序中硬编码用户名和密码,任何人只要获取了源代码的一个副本(或者对已编译的代码进行反向工程),
                 * 就可以看到这个信息,从而使整个安全机制沦为笑话
                 */
                 /*
                  * SqlConnection myConnection = new SqlConnection();
                  * string userName="...";
                  * string password="...";
                  * string connString = $"User ID={userName};password={password};Initial Catalog=Northwind;Data Source=你的计算机\\SQLExpress";
                  * myConnection.ConnectionString = connString;
                 */
                dataConnection.ConnectionString = builder.ConnectionString;//把构建的字符串给数据库连接
                dataConnection.Open();
                Console.Write("请输入一个客户ID(5个字符):");
                string customerId = Console.ReadLine();//读取一个字符串

                SqlCommand dataCommand = new SqlCommand();//新建一个Sql命令
                dataCommand.Connection = dataConnection;
                dataCommand.CommandType = CommandType.Text;//命令类型是文本类型
                dataCommand.CommandText = $"select OrderID,OrderDate,ShippedDate,ShipName,ShipAddress,ShipCity,ShipCountry from Orders where CustomerID=@CustomerIdParam";
                /*
                 * @CustomerIdParam是一个SQL参数的点位符(@符号向数据提供程序指明这是一个参数,而不是数据库中一列)
                 * 这样是为了避免SQL注入攻击
                 */
                //创建一个Sql参数,可以在执行SqlCommand对象时替换@声明的变量,变量被声明成数据库Char类型(定长字符串的SQL Server等价物),最长5个字符串
                SqlParameter param = new SqlParameter("@CustomerIdParam", SqlDbType.Char, 5);
                param.Value = customerId;
                dataCommand.Parameters.Add(param);
                //dataCommand.Parameters.Add("@CustomerIdParam", SqlDbType.VarChar, 80).Value = customerId;

                Console.WriteLine($"About to find orders for customer {customerId}");
                SqlDataReader dataReader = dataCommand.ExecuteReader();
                //SqlDataReader执行SQL命令,得到返回数据,而且每次只获取一行,并且获取一行后不在这行保留任何锁,
                //避免了锁定数据库的某行,从而使其它进程无法读取
                while (dataReader.Read())
                {
                    
                    int orderId = dataReader.GetInt32(0);
                    if (dataReader.IsDBNull(2))//判断一下第二列数据是否为空,使用get读取空数据会抛出异常
                    {
                        Console.WriteLine($"Order {orderId} not yet shiped\n\n");
                    }
                    else
                    {
                        DateTime orderDate = dataReader.GetDateTime(1);
                        DateTime dateTime = dataReader.GetDateTime(2);
                        string shipName = dataReader.GetString(3);
                        string shipAddress = dataReader.GetString(4);
                        string shipCity = dataReader.GetString(5);
                        string shipCountry = dataReader.GetString(6);
                        Console.WriteLine($"Order:{orderId}\nPlaced:{orderDate}\nshipped:{dateTime}\nTo Address:{shipName}\n{shipAddress}\n{shipCity}\n{shipCountry}\n\n");
                    }
                    
                }
                dataReader.Close();
            }
            catch (SqlException e)
            {
                Console.WriteLine($"Error accessing the database:{e.Message}");
            }
            finally
            {
                dataConnection.Close();
            }
        }
    }
}

使用LINQ to SQL查询数据库

LINQ to SQL提供了一个高级的抽象,使你不再需要操心具体如何构建ADO.NET Command对象,不再需要操心如何遍历由DataReader对象返回的结果集,也不再需要操心如何使用各种GetXXX方法来逐列的获取数据

我们需要先定义一个实体类,对应数据库中的一张表,与新建一张相似的表类似
在这个类中针对表中自己感兴趣的每一列,都建一个属性(并不需要包含所有的列),但是没有建相应属性的列肯定是获取不到数据的。

 	[Table(Name = "Products")] //name是表名,如果省略默认是类名
    class Product
    {
        [Column(IsPrimaryKey = true, CanBeNull = false)]//定义它是主键,不能为空,其实也有name属性,不指定默认数据库列名和属性名称一致
        public int ProductID { get; set; }

        [Column(CanBeNull = false)]
        public string ProductName { get; set; }

        [Column]
        public int? SupplierID { get; set; }

        [Column(DbType = "money")]//因为C#中没有money类型,所以要映射成decimal(虽然默认自己就会把money映射成decimal,但是为了语法展示,所以写出来了)
        public decimal? UnitPrice { get; set; }
    }

然后就简单了

using System;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Data.SqlClient;

namespace LINQ
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
            builder.DataSource = ".\\SQLExpress";
            builder.InitialCatalog = "Northwind";
            builder.IntegratedSecurity = true;

            DataContext db = new DataContext(builder.ConnectionString);

            Table<Product> products = db.GetTable<Product>();
            //实时数据
            //var productsQuery = from p in products select p;
            //foreach (var product in productsQuery)
            //{
            //    Console.WriteLine($"ID:{product.ProductID},Name:{product.ProductName},Supplier:{product.SupplierID},Price{product.UnitPrice:C}");
            //}
            //历史数据
            //var productsQuery = from p in products.ToList() select p;
            //foreach (var product in productsQuery)
            //{
            //    Console.WriteLine($"ID:{product.ProductID},Name:{product.ProductName},Supplier:{product.SupplierID},Price{product.UnitPrice:C}");
            //}
            foreach (var product in products)
            {
                Console.WriteLine($"ID:{product.ProductID},Name:{product.ProductName},Supplier:{product.SupplierID},Price{product.UnitPrice:C}");
            }

        }
    }

    [Table(Name = "Products")]
    class Product
    {
        [Column(IsPrimaryKey = true, CanBeNull = false)]
        public int ProductID { get; set; }

        [Column(CanBeNull = false)]
        public string ProductName { get; set; }

        [Column]
        public int? SupplierID { get; set; }

        [Column(DbType = "money")]
        public decimal? UnitPrice { get; set; }
    }
}

是不是比上面简单多了!
而实际上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值