EF Core使用SQL调用返回其他类型的查询
假设你想要 SQL 本身编写,而不使用 LINQ。 需要运行 SQL 查询中返回实体对象之外的内容。 在 EF Core 中,执行该操作的另一种方法是编写 ADO.NET 代码,并从 EF 获取数据库连接。
public async Task<ActionResult> About() { List<EnrollmentDateGroup> groups = new List<EnrollmentDateGroup>(); var conn = _context.Database.GetDbConnection(); try { await conn.OpenAsync(); using (var command = conn.CreateCommand()) { string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount " + "FROM Person " + "WHERE Discriminator = 'Student' " + "GROUP BY EnrollmentDate"; command.CommandText = query; DbDataReader reader = await command.ExecuteReaderAsync(); if (reader.HasRows) { while (await reader.ReadAsync()) { var row = new EnrollmentDateGroup { EnrollmentDate = reader.GetDateTime(0), StudentCount = reader.GetInt32(1) }; groups.Add(row); } } reader.Dispose(); } } finally { conn.Close(); } return View(groups); }
ASP.NET Core 2.0 使用NLog实现日志记录
1、安装NuGet包
运行:Install-Package NLog.Web.AspNetCore
运行:Install-Package NLog
在csproj中编辑:
<PackageReference Include="NLog" Version="4.5.3" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.5.3" />
2、创建一个nlog.config文件。
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" throwConfigExceptions="true" internalLogLevel="info" internalLogFile="D:\temp\internal-nlog.txt"> <!-- 要写的目标--> <targets> <!--将日志写入文件 --> <target xsi:type="File" name="allfile" fileName="D:\temp\nlog-all-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" /> <!-- 启用asp.net核心布局渲染器 --> <target xsi:type="File" name="ownFile-web" fileName="D:\temp\nlog-own-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}" /> </targets> <!-- 从记录器名称映射到目标的规则 --> <rules> <!--所有的记录,包括从微软--> <logger name="*" minlevel="Trace" writeTo="allfile" /> <!--跳过非关键微软日志,因此只记录自己的日志--> <logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole --> <logger name="*" minlevel="Trace" writeTo="ownFile-web" /> </rules> </nlog>
3、在csproj
手动编辑文件并添加
<ItemGroup> <Content Update="nlog.config" CopyToOutputDirectory="Always" /> </ItemGroup>
4、更新program.cs
public static void Main(string[] args) { // NLog:首先设置记录器以捕获所有错误 var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); try { logger.Debug("init main"); BuildWebHost(args).Run(); } catch (Exception exception) { // NLog:catch安装错误 logger.Error(exception, "Stopped program because of exception"); throw; } finally { //确保在退出应用程序之前刷新并停止内部定时器/线程(避免Linux上的分段错误) NLog.LogManager.Shutdown(); } } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .ConfigureLogging(logging => { logging.ClearProviders(); logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); }) .UseNLog() // NLog:setup NLog用于依赖注入 .Build();
5、配置appsettings.json
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Warning", "Microsoft": "Information" } } }
6、写日志
private readonly ILogger _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; _logger.LogDebug(1, "NLog injected into HomeController"); } public IActionResult Index() { _logger.LogInformation("Hello, this is the index!"); return View(); }
7、输出示例
CSS 3D transforms
https://www.creativebloq.com/css3/20-stunning-examples-css-3d-transforms-11112759
https://github.com/fofr/paulrhayes.com-experiments
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
<!DOCTYPE html>
<html lang=
"en"
>
<head>
<!-- Hey there, thanks
for
looking at the source. Skip down until you see the experiment start comments -->
<meta charset=
"UTF-8"
/>
<meta http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
/>
<meta name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
/>
<title>Experiment: A tetrahedron built with CSS 3D transforms — Paul Hayes</title>
<style type=
"text/css"
>
#pyramid {
position: relative;
margin: 100px auto;
height: 500px;
width: 100px;
-webkit-transform-style: preserve-3d;
-webkit-animation: spin 10s linear infinite;
-webkit-transform-origin: 116px 200px 116px;
-moz-transform-style: preserve-3d;
-moz-animation: spin 10s linear infinite;
-moz-transform-origin: 116px 200px 116px;
-ms-transform-style: preserve-3d;
-ms-animation: spin 10s linear infinite;
-ms-transform-origin: 116px 200px 116px;
transform-style: preserve-3d;
animation: spin 10s linear infinite;
transform-origin: 116px 200px 116px;
}
@-webkit-keyframes spin {
from
{
-webkit-transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
to {
-webkit-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
}
}
@-moz-keyframes spin {
from
{
-moz-transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
to {
-moz-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
}
}
@-ms-keyframes spin {
from
{
-ms-transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
to {
-ms-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
}
}
@keyframes spin {
from
{
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
to {
transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
}
}
#pyramid > div {
position: absolute;
border-style: solid;
border-width: 200px 0 200px 346px;
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
/* Put some text on each face */
#pyramid > div:after {
position: absolute;
content:
"Triangle"
;
color: #fff;
left: -250px;
text-align: center;
}
#pyramid > div:first-child {
border-color: transparent transparent transparent rgba(50, 50, 50, 0.6);
-webkit-transform: rotateY(-19.5deg) rotateX(180deg) translateY(-400px);
-moz-transform: rotateY(-19.5deg) rotateX(180deg) translateY(-400px);
-ms-transform: rotateY(-19.5deg) rotateX(180deg) translateY(-400px);
transform: rotateY(-19.5deg) rotateX(180deg) translateY(-400px);
}
#pyramid > div:nth-child(2) {
border-color: transparent transparent transparent rgba(50, 50, 50, 0.6);
-webkit-transform: rotateY(90deg) rotateZ(60deg) rotateX(180deg) translateY(-400px);
-moz-transform: rotateY(90deg) rotateZ(60deg) rotateX(180deg) translateY(-400px);
-ms-transform: rotateY(90deg) rotateZ(60deg) rotateX(180deg) translateY(-400px);
transform: rotateY(90deg) rotateZ(60deg) rotateX(180deg) translateY(-400px);
}
#pyramid > div:nth-child(3) {
border-color: transparent transparent transparent rgba(50, 50, 50, 0.9);
-webkit-transform: rotateX(60deg) rotateY(19.5deg);
-moz-transform: rotateX(60deg) rotateY(19.5deg);
-ms-transform: rotateX(60deg) rotateY(19.5deg);
transform: rotateX(60deg) rotateY(19.5deg);
}
#pyramid > div:nth-child(4) {
border-color: transparent transparent transparent rgba(50, 50, 50, 0.8);
-webkit-transform: rotateX(-60deg) rotateY(19.5deg) translateX(-116px) translateY(-200px) translateZ(326px);
-moz-transform: rotateX(-60deg) rotateY(19.5deg) translateX(-116px) translateY(-200px) translateZ(326px);
-ms-transform: rotateX(-60deg) rotateY(19.5deg) translateX(-116px) translateY(-200px) translateZ(326px);
transform: rotateX(-60deg) rotateY(19.5deg) translateX(-116px) translateY(-200px) translateZ(326px);
}
</style>
</head>
<body>
<div
class
=
"experiment-body clearfix"
>
<div
class
=
"test test-3dtransforms"
>
<!--
**************************
Start of experiment
**************************
-->
<article id=
"viewport"
>
<section id=
"pyramid"
>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
</article>
<!--
**************************
End of experiment
**************************
-->
</div>
</div>
</body>
</html>
|
cSharp:use Activator.CreateInstance with an Interface?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
///<summary>
///数据访问工厂
///生成時間2015-2-13 10:54:34
///塗聚文(Geovin Du)
/// (利用工厂模式+反射机制+缓存机制,实现动态创建不同的数据层对象接口)
///</summary>
public
class
AbstractFactory
{
protected
static
string
path = ConfigurationManager.AppSettings[
"WebDAL"
];
//"DAL";//生成的DLL文件名
/// <summary>
/// 数据库类型
/// </summary>
protected
static
string
dalType
{
get
{
if
(path.Contains(
"AccessDAL"
))
{
//path = "AcessDAL";
return
"AccessDAL"
;
}
else
if
(path==
"DAL"
)
{
// path = "DAL";//生成的DLL文件名
return
"SqlServerDAL"
;
//命名空间名称
}
else
if
(path.Contains(
"MySQLDAL"
))
{
return
"MySQLDAL"
;
}
else
if
(path.Contains(
"DALSQLite"
))
{
//path = "DALSQLite";
return
"SQLiteDAL"
;
}
else
if
(path.Contains(
"PostgreSQLDAL"
))
{
// path = "DALPostgreSQL";
return
"PostgreSQLDAL"
;
}
else
if
(path.Contains(
"OracleDAL"
))
{
return
"OracleDAL"
;
}
else
{
//path = "DAL";
return
"SqlServerDAL"
;
}
}
}
public
AbstractFactory()
{ }
///<summary>
///分页接口
/// </summary>
///<returns></returns>
public
static
ISelectPage CreateSelectPage()
{
//ISelectPage page = new SelectPage();
//return page;
string
className =
"GeovinDu."
+ dalType +
".SelectPage"
;
return
(ISelectPage)Assembly.Load(path).CreateInstance(className);
//命名空间名称GeovinDu.SqlServerDAL
//path = "AcessDAL";//生成的DLL文件名
}
///<summary>
///CompanyBranch接口
/// </summary>
///<returns></returns>
public
static
ICompanyBranch CreateCompanyBranch(
string
_databaseprefix,
string
_sysdatarolefix)
{
//ICompanyBranch iCompanyBranch = new CompanyBranchDAL();
//return iCompanyBranch;
string
className =
"GeovinDu."
+ dalType +
".CompanyBranchDAL"
;
//(_databaseprefix, _sysdatarolefix)
return
(ICompanyBranch)Assembly.Load(path).CreateInstance(className);
//GeovinDu.SqlServerDAL
}
///<summary>
///EnterpriseType接口
/// </summary>
///<returns></returns>
public
static
IEnterpriseType CreateEnterpriseType(
string
_databaseprefix,
string
_sysdatarolefix)
{
//IEnterpriseType iEnterpriseType = new EnterpriseTypeDAL();
//return iEnterpriseType;
string
className =
"GeovinDu."
+ dalType +
".EnterpriseTypeDAL"
;
return
(IEnterpriseType)Assembly.Load(path).CreateInstance(className);
}
///<summary>
///LoginDiaryList接口
/// </summary>
///<returns></returns>
public
static
ILoginDiaryList CreateLoginDiaryList(
string
_databaseprefix,
string
_sysdatarolefix)
{
//ILoginDiaryList iLoginDiaryList = new LoginDiaryListDAL();
//return iLoginDiaryList;
string
className =
"GeovinDu."
+ dalType +
".LoginDiaryListDAL"
;
//(_databaseprefix, _sysdatarolefix)
return
(ILoginDiaryList)Assembly.Load(path).CreateInstance(className);
}
///<summary>
///OperatingUser接口
///https://msdn.microsoft.com/zh-cn/library/ms173128(VS.80).aspx
///https://stackoverflow.com/questions/2202381/reflection-how-to-invoke-method-with-parameters
/// </summary>
///<returns></returns>
public
static
IOperatingUser CreateOperatingUser(
string
_databaseprefix,
string
_sysdatarolefix)
{
//IOperatingUser iOperatingUser = new OperatingUserDAL(_databaseprefix, _sysdatarolefix);
//return iOperatingUser;
IOperatingUser iOperatingUser =
null
;
string
className =
"GeovinDu."
+ dalType +
".OperatingUserDAL"
;
//(_databaseprefix, _sysdatarolefix)
//return (IOperatingUser)Assembly.Load(path).CreateInstance(className);
//string className = "GeovinDu.SQLiteDAL.OperatingUserDAL";
//Assembly assembly = Assembly.LoadFrom(@"G:\winxp备份\PayrollPrint4\PayrollPrint\bin\Release\DALSQLite.dll");
// object oo = assembly.CreateInstance(className); //得到对象命名空间名
// MethodInfo methodinfo = assembly.GetType("GeovinDu.GeovinDu.SQLiteDAL.OperatingUserDAL").GetMethod("OperatingUserDAL"); //得到方法
//Object obj = methodinfo.Invoke(oo, new object[] { _databaseprefix, _sysdatarolefix });
//IOperatingUser iOperatingUser = (IOperatingUser)obj;
object
obj = Assembly.Load(path).CreateInstance(className);
Type t2 = obj.GetType();
// Type.GetType("GeovinDu.SQLiteDAL.OperatingUserDAL", false, true);
if
(t2 !=
null
)
{
iOperatingUser = (OperatingUserDAL)Activator.CreateInstance(t2,
new
object
[] { });
//Assembly.Load(path).CreateInstance(className); //值為空
}
//iOperatingUser = (IOperatingUser)Activator.CreateInstance(System.Type.GetType(className));
return
iOperatingUser;
}
///<summary>
///PrintWordDocumentTemplateList接口
/// </summary>
///<returns></returns>
public
static
IPrintWordDocumentTemplateList CreatePrintWordDocumentTemplateList(
string
_databaseprefix,
string
_sysdatarolefix)
{
//IPrintWordDocumentTemplateList iPrintWordDocumentTemplateList = new PrintWordDocumentTemplateListDAL();
//return iPrintWordDocumentTemplateList;
string
className =
"GeovinDu."
+ dalType +
".PrintWordDocumentTemplateListDAL"
;
//(_databaseprefix, _sysdatarolefix)
return
(IPrintWordDocumentTemplateList)Assembly.Load(path).CreateInstance(className);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public
static
ISysConfig CreateSysConfig()
{
string
className =
"GeovinDu."
+ dalType +
".SysConfigDAL"
;
return
(ISysConfig)Assembly.Load(path).CreateInstance(className);
//databaseprefix = _databaseprefix;
//ISysConfig iSysConfig = new DAL.SysConfigDAL();
//return iSysConfig;
}
}
|
https://github.com/fabriciorissetto/CustomActivator
https://www.codeproject.com/Articles/55710/Reflection-in-NET
https://www.codeproject.com/Articles/14593/A-General-Fast-Method-Invoker
https://github.com/ekonbenefits/impromptu-interface
https://www.codeproject.com/Articles/109868/General-DynamicObject-Proxy-and-Fast-Reflection-Pr
https://www.codeproject.com/articles/15089/an-abstract-factory-using-app-config-and-reflectio
https://www.microsoft.com/net/download/windows
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
/// <summary>
/// 无构造函数的用法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dllname"></param>
/// <param name="fullClassName"></param>
/// <returns></returns>
public
static
T CreateInstance<T>(
string
dllname,
string
fullClassName)
{
//string fullClassName = nameSpace + "." + className;
return
(T)Assembly.Load(dllname).CreateInstance(fullClassName);
}
/// <summary>
/// 有構造函數的用法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dllname"></param>
/// <param name="fullName"></param>
/// <param name="parameters">构造函数的参数</param>
/// <returns></returns>
public
static
T CreateInstance<T>(
string
dllname,
string
fullName,
object
[] parameters)
{
try
{
//string fullName = nameSpace + "." + className;//命名空间.类型名
object
ect = Assembly.Load(dllname).CreateInstance(fullName,
true
, System.Reflection.BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null
, parameters,
null
,
null
);
//加载程序集,创建程序集里面的 命名空间.类型名 实例
return
(T)ect;
//类型转换并返回
}
catch
{
//发生异常,返回类型的默认值
return
default
(T);
}
}
/// <summary>
/// 有構造函數的用法
/// geovindu
/// 塗聚文 涂聚文
/// Geovin Du
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fullTypeName"></param>
/// <param name="paramArray">构造函数的参数</param>
/// <returns></returns>
public
static
T CreateInstance<T>(
string
fullTypeName,
object
[] parameters)
{
return
(T)Activator.CreateInstance(Type.GetType(fullTypeName), parameters);
}
/// <summary>
/// 有構造函數的用法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dllname"></param>
/// <param name="fullTypeName"></param>
/// <param name="paramArray"></param>
/// <returns></returns>
public
static
T CreateInstanceActivator<T>(
string
dllname,
string
fullTypeName,
object
[] paramArray)
{
Assembly tempAssembly = Assembly.Load(dllname);
Type typeofControl = tempAssembly.GetType(fullTypeName);
return
(T)Activator.CreateInstance(typeofControl, paramArray);
}
/// <summary>
/// 有構造函數的用法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fullTypeName"></param>
/// <param name="paramArray"></param>
/// <returns></returns>
//public static T CreateInstance<T>(string fullTypeName, params object[] paramArray)
//{
// return (T)Activator.CreateInstance(Type.GetType(fullTypeName), args: paramArray);
//}
/// <summary>
/// 无构造函数的用法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fullTypeName"></param>
/// <returns></returns>
public
static
T CreateInstance<T>(
string
fullTypeName)
{
return
(T)Activator.CreateInstance(Type.GetType(fullTypeName));
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
string
dir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string
pdll = dir +
@"\DALSQLite.dll"
;
Type type = Type.GetType(
"System.String"
);
object
obj = Assembly.Load(
"DALSQLite"
).CreateInstance(className,
true
, System.Reflection.BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null
, parameter,
null
,
null
);
//className
//构造函数
Type t2 = obj.GetType();
object
oodu = Activator.CreateInstance(t2,parameter);
//t2.GetConstructors
if
(oodu !=
null
)
{
string
du = oodu.ToString();
}
string
[] str = { _databaseprefix, _sysdatarolefix };
//Type type = Type.GetType("System.String");
Assembly pluginAssembly = Assembly.LoadFrom(pdll);
Type dynclasstype = pluginAssembly.GetType(className);
Type[] pt =
new
Type[2];
pt[0] =
typeof
(
string
);
// typeof(string);
pt[1] =
typeof
(
string
);
//typeof(string);
//object dynobj = Activator.CreateInstance(dynclasstype);//有構造函數不可以用
object
dynobj = Activator.CreateInstance(dynclasstype,parameter);
if
(dynobj !=
null
)
{
dynobj.ToString();
ConstructorInfo[] cinfos = dynclasstype.GetConstructors();
// (pt);
ConstructorInfo cinfo = cinfos[0];
// dynclasstype.GetConstructor(pt);
if
(cinfo !=
null
)
{
string
na = cinfo.Name;
ParameterInfo[] psci = cinfo.GetParameters();
foreach
(ParameterInfo pici
in
psci)
//遍历并打印所该构造函数的所有参数
{
string
nci=pici.ParameterType.ToString() +
" :"
+ pici.Name +
","
;
}
}
}
Type classType = pluginAssembly.GetType(className);
StringBuilder g =
new
StringBuilder();
ConstructorInfo[] ci = t2.GetConstructors();
//获取类的所有构造函数
foreach
(ConstructorInfo c
in
ci)
//遍历每一个构造函数
{
c.ToString();
ParameterInfo[] ps = c.GetParameters();
//取出每个构造函数的所有参数
foreach
(ParameterInfo pi
in
ps)
//遍历并打印所该构造函数的所有参数
{
g.Append(pi.ParameterType.ToString() +
" :"
+ pi.Name +
","
);
}
}
|
SqlHelper DBHelper
根据自己项目的开发需要,整理了一个SqlHelper类
相比较网上通用的SqlHelper类方法主要有一下几点的不同:
1.因为要操作多个数据库,所以数据库连接字符串没有写死到方法里,作为参数提供出来。
2.因为涉及到多表多库的操作,涉及到数据库级别的事物,以及逻辑业务上的事物,因此,要从最基元的部分就尽可能屏蔽问题,进行严格的事物处理。
方法如下:
个人认为使用率较高也较为方便的是 ExecuteNonQuery (增、删、改),ExecuteDataTable(支持存储过程和SQL语句查询,返回tadatable)
其中ExecuteNonQuery中的 iCount 参数就是用来进行事物处理的
/// <summary>
/// 对数据库执行增、删、改命令
/// </summary>
/// <param name="sql">T-Sql语句</param>
/// <param name="pa">参数数组</param>
/// <param name="iCount">成功情况下影响行数</param>
/// <returns>受影响的记录数</returns>
public static int ExecuteNonQuery(string connectionString, string sql, SqlParameter[] pa, int iCount)
{
using (SqlConnection Connection = new SqlConnection(connectionString))
{
Connection.Open();
SqlTransaction trans = Connection.BeginTransaction();
try
{
SqlCommand cmd = new SqlCommand(sql, Connection);
cmd.Transaction = trans;
if (pa != null)
{
cmd.Parameters.AddRange(pa);
}
if (Connection.State != ConnectionState.Open)
{
Connection.Open();
}
int result = cmd.ExecuteNonQuery();
if (iCount != 0 && iCount != result)
{
trans.Rollback();
return 0;
}
trans.Commit();
return result;
}
catch (Exception ex)
{
trans.Rollback();
return 0;
}
}
}
/// <summary>
/// 执行指定数据库连接对象的命令,指定存储过程参数,返回DataTable
/// </summary>
/// <param name="connectionString">连接字符串</param>
/// <param name="type">命令类型(T-Sql语句或者存储过程)</param>
/// <param name="sql">T-Sql语句或者存储过程的名称</param>
/// <param name="pa">参数数组</param>
/// <returns>结果集DataTable</returns>
public static DataTable ExecuteDataTable(string connectionString, CommandType type, string sql, params SqlParameter[] pa)
{
using (SqlConnection Connection = new SqlConnection(connectionString))
{
try
{
if (Connection.State != ConnectionState.Open)
Connection.Open();
DataSet ds = new DataSet();
SqlCommand cmd = new SqlCommand(sql, Connection);
cmd.CommandType = type;
if (pa != null)
cmd.Parameters.AddRange(pa);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
if (ds.Tables != null && ds.Tables.Count > 0)
{
return ds.Tables[0];
}
}
catch (Exception ex)
{
return null;
}
return null;
}
}
/// <summary>
/// 查询结果集中第一行第一列的值
/// </summary>
/// <param name="connectionString">连接字符串</param>
/// <param name="sql">T-Sql语句</param>
/// <param name="pa">参数数组</param>
/// <returns>第一行第一列的值</returns>
public static int ExecuteScalar(string connectionString, string sql, SqlParameter[] pa)
{
using (SqlConnection Connection = new SqlConnection(connectionString))
{
if (Connection.State != ConnectionState.Open)
Connection.Open();
SqlCommand cmd = new SqlCommand(sql, Connection);
if (pa != null)
cmd.Parameters.AddRange(pa);
int result = Convert.ToInt32(cmd.ExecuteScalar());
return result;
}
}
/// <summary>
/// 创建数据读取器
/// </summary>
/// <param name="connectionString">连接字符串</param>
/// <param name="sql">T-Sql语句</param>
/// <param name="pa">参数数组</param>
/// <param name="Connection">数据库连接</param>
/// <returns>数据读取器</returns>
public static SqlDataReader ExecuteReader(string connectionString, string sql, SqlParameter[] pa, SqlConnection conn)
{
if (conn.State != ConnectionState.Open)
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
if (pa != null)
cmd.Parameters.AddRange(pa);
SqlDataReader reader = cmd.ExecuteReader();
return reader;
}
C# Thread.Abort方法真的让线程停止了吗?
大家都知道在C#里面,我们可以使用 Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Thread.Abort方法后线程就立刻停止了吗? 答案是:不是!
下面我们来解释一下Abort方法是如何工作的。因为公用语言运行时管理了所有的托管的线程,同样它能在每个线程内抛出异常。Abort方法能在目标线程中抛出一个ThreadAbortException异常从而导致目标线程的终止。不过Abort方法被调用后,目标线程可能并不是马上就终止了。因为只要目标线程正在调用非托管的代码而且还没有返回的话,该线程就不会立即终止。而如果目标线程在调用非托管的代码而且陷入了一个死循环的话,该目标线程就根本不会终止。不过这种情况只是一些特例,更多的情况是目标线程在调用托管的代码,一旦Abort被调用那么该线程就立即终止了。
其实一个线程在运行时,我们可以通过Thread.ThreadState属性读出它的状态,正在运行的线程状态就是ThreadState.Running。然后如果我们想强制停止正在执行的线程,就会调用Thread.Abort方法,但是Thread.Abort方法做的事情只是在线程上抛出了一个ThreadAbortException异常,然后将线程的状态置为ThreadState.AbortRequested,MSDN对AbortRequested状态的解释是:已对线程调用了 Thread.Abort 方法,但线程尚未收到试图终止它的挂起的System.Threading.ThreadAbortException,也就是说线程在ThreadState.AbortRequested状态时表示即将结束但是还没有真正结束。可是Thread.Abort方法将线程的状态置为ThreadState.AbortRequested后就立马返回了,而线程真正结束后的状态应该是ThreadState.Aborted,所以一定要注意在调用了Thread.Abort方法后,要记得循环检查Thread.ThreadState属性的值或者调用Thread.Join方法来确保被终止线程已经真正停止,只有当Thread.ThreadState属性为Aborted或Thread.Join方法返回时,才表示线程真正结束了。
下面我就写一个示例代码来说明在调用Thread.Abort方法后,怎样保证线程停止后代码才会继续执行
var thread = new Thread( new ThreadStart( () => { while (true) { //该线程会进行无限循环,自己不会结束 Thread.Sleep(100); } })); thread.IsBackground = true; thread.Start();//启动线程 thread.Abort();//调用Thread.Abort方法试图强制终止thread线程 //上面调用Thread.Abort方法后线程thread不一定马上就被终止了,所以我们在这里写了个循环来做检查,看线程thread是否已经真正停止。其实也可以在这里使用Thread.Join方法来等待线程thread终止,Thread.Join方法做的事情和我们在这里写的循环效果是一样的,都是阻塞主线程直到thread线程终止为止 while (thread.ThreadState!=ThreadState.Aborted) { //当调用Abort方法后,如果thread线程的状态不为Aborted,主线程就一直在这里做循环,直到thread线程的状态变为Aborted为止 Thread.Sleep(100); } //当跳出上面的循环后就表示我们启动的线程thread已经完全终止了
不过请记住使用Thread.Abort方法来终止正在执行的线程并不是一个好的方法,因为Abort方法是通过在线程上抛异常来终止线程的,这样可能会产生一些意想不到的问题。最好的办法是在启动的线程中加信号灯,当想要终止线程执行时就更改信号灯的状态,启动的线程当读到信号灯状态改变后自己结束代码的执行,这才是最安全的做法。
原文链接:https://www.cnblogs.com/OpenCoder/p/4587249.html
注意!你的Thread.Abort方法真的让线程停止了吗?
大家都知道在C#里面,我们可以使用 Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Thread.Abort方法后线程就立刻停止了吗? 答案是:不是!
下面我们来解释一下Abort方法是如何工作的。因为公用语言运行时管理了所有的托管的线程,同样它能在每个线程内抛出异常。Abort方法能在目标线程中抛出一个ThreadAbortException异常从而导致目标线程的终止。不过Abort方法被调用后,目标线程可能并不是马上就终止了。因为只要目标线程正在调用非托管的代码而且还没有返回的话,该线程就不会立即终止。而如果目标线程在调用非托管的代码而且陷入了一个死循环的话,该目标线程就根本不会终止。不过这种情况只是一些特例,更多的情况是目标线程在调用托管的代码,一旦Abort被调用那么该线程就立即终止了。
其实一个线程在运行时,我们可以通过Thread.ThreadState属性读出它的状态,正在运行的线程状态就是ThreadState.Running。然后如果我们想强制停止正在执行的线程,就会调用Thread.Abort方法,但是Thread.Abort方法做的事情只是在线程上抛出了一个ThreadAbortException异常,然后将线程的状态置为ThreadState.AbortRequested,MSDN对AbortRequested状态的解释是:已对线程调用了 Thread.Abort 方法,但线程尚未收到试图终止它的挂起的System.Threading.ThreadAbortException,也就是说线程在ThreadState.AbortRequested状态时表示即将结束但是还没有真正结束。可是Thread.Abort方法将线程的状态置为ThreadState.AbortRequested后就立马返回了,而线程真正结束后的状态应该是ThreadState.Aborted,所以一定要注意在调用了Thread.Abort方法后,要记得循环检查Thread.ThreadState属性的值或者调用Thread.Join方法来确保被终止线程已经真正停止,只有当Thread.ThreadState属性为Aborted或Thread.Join方法返回时,才表示线程真正结束了。
下面我就写一个示例代码来说明在调用Thread.Abort方法后,怎样保证线程停止后代码才会继续执行
var thread = new Thread( new ThreadStart( () => { while (true) { //该线程会进行无限循环,自己不会结束 Thread.Sleep(100); } })); thread.IsBackground = true; thread.Start();//启动线程 thread.Abort();//调用Thread.Abort方法试图强制终止thread线程 //上面调用Thread.Abort方法后线程thread不一定马上就被终止了,所以我们在这里写了个循环来做检查,看线程thread是否已经真正停止。其实也可以在这里使用Thread.Join方法来等待线程thread终止,Thread.Join方法做的事情和我们在这里写的循环效果是一样的,都是阻塞主线程直到thread线程终止为止 while (thread.ThreadState!=ThreadState.Aborted) { //当调用Abort方法后,如果thread线程的状态不为Aborted,主线程就一直在这里做循环,直到thread线程的状态变为Aborted为止 Thread.Sleep(100); } //当跳出上面的循环后就表示我们启动的线程thread已经完全终止了
不过请记住使用Thread.Abort方法来终止正在执行的线程并不是一个好的方法,因为Abort方法是通过在线程上抛异常来终止线程的,这样可能会产生一些意想不到的问题。最好的办法是在启动的线程中加信号灯,当想要终止线程执行时就更改信号灯的状态,启动的线程当读到信号灯状态改变后自己结束代码的执行,这才是最安全的做法。