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>
布局渲染器是在布局中使用的模板宏,例如${message}
,${level}
等等
NLog支持创建自定义布局渲染器。有关更多信息,请参阅:扩展NLog
NLog软件包 $ {activityid} - 将一个System.Diagnostics跟踪关联ID放入日志中。 $ {all-event-properties} - 记录所有事件上下文数据。 $ {appdomain} - 当前的应用程序域。 $ {assembly-version} - 默认应用程序域中可执行文件的版本。 $ {basedir} - 当前应用程序域的基本目录。 $ {callsite} - 呼叫站点(类名称,方法名称和源信息)。 $ {callsite-linenumber} - 呼叫站点源行号。 $ {counter} - 一个计数器值(每个布局渲染都会增加)。 $ {currentdir} - 应用程序的当前工作目录。 $ {date} - 当前日期和时间。 $ {document-uri} - 托管当前Silverlight应用程序的HTML页面的URI。 $ {environment} - 环境变量。 $ {event-properties} - 记录事件属性数据 - 重命名$ {event-context}。 $ {exception} - 通过调用其中一个Logger * Exception()方法提供的异常信息。 $ {file-contents} - 渲染指定文件的内容。 $ {gc} - 关于垃圾收集器的信息。 $ {gdc} - 全局诊断上下文项目。字典结构来保存每个应用程序实例值。 $ {guid} - 全局唯一标识符(GUID)。 $ {identity} - 线程标识信息(名称和认证信息)。 $ {install-context} - 安装参数(传递给InstallNLogConfig)。 $ {level} - 日志级别。 $ {literal} - 一个字符串文字。 $ {log4jxmlevent} - 与log4j,Chainsaw和NLogViewer兼容的XML事件描述。 $ {logger} - 记录器名称。 $ {longdate} - 日期和时间格式很长,可排序yyyy-MM-dd HH:mm:ss.ffff。 $ {machinename} - 进程正在运行的机器名称。 $ {mdc} - 映射的诊断上下文 - 一个线程局部结构。 $ {mdlc} - 异步映射的诊断上下文 - 一个线程局部结构。 $ {message} - 格式化的日志消息。 $ {ndc} - 嵌套的诊断上下文 - 一个线程局部结构。 $ {ndlc} - 异步嵌套诊断上下文 - 一个线程局部结构。 $ {newline} - 换行符。 $ {nlogdir} - NLog.dll所在的目录。 $ {performancecounter} - 性能计数器。 $ {processid} - 当前进程的标识符。 $ {processinfo} - 关于正在运行的进程的信息。 $ {processname} - 当前进程的名称。 $ {processtime} - 格式为HH:mm:ss.mmm的处理时间。 $ {qpc} - 高精度计时器,基于从QueryPerformanceCounter()返回的值(可选地转换为秒)。 $ {registry} - 来自注册表的值。 $ {sequenceid} - 日志序列标识 $ {shortdate} - 可排序格式的短日期yyyy-MM-dd。 $ {sl-appinfo} - 有关Silverlight应用程序的信息。 $ {specialfolder} - 系统特殊文件夹路径(包括我的文档,我的音乐,程序文件,桌面等)。 $ {stacktrace} - 堆栈跟踪渲染器。 $ {tempdir} - 一个临时目录。 $ {threadid} - 当前线程的标识符。 $ {threadname} - 当前线程的名称。 $ {ticks} - 当前日期和时间的Ticks值。 $ {time} - 以24小时可排序格式HH:mm:ss.mmm的时间。 $ {var} - 渲染变量(4.1中新增) $ {windows-identity} - 线程Windows身份信息(用户名)。 包装 $ {cached} - 将缓存应用于另一个布局输出。 $ {filesystem-normalize} - 通过用安全字符替换文件名中不允许的字符。 $ {json-encode} - 使用JSON规则转义另一个布局的输出。 $ {lowercase} - 将另一个布局输出的结果转换为小写。 $ {onexception} - 仅在为日志消息定义异常时才输出内部布局。 $ {pad} - 将填充应用于另一个布局输出。 $ {replace} - 用另一个字符串替换另一个布局输出中的字符串。 $ {replace-newlines} - 用另一个字符串替换换行符。 $ {rot13} - 用ROT-13解码“encrypted”文本。 $ {trim-whitespace} - 修剪另一个布局渲染器的结果中的空白。 $ {uppercase} - 将另一个布局输出的结果转换为大写。 $ {url-encode} - 编码另一个布局输出的结果以用于URL。 $ {when} - 只有在满足指定条件时才输出内部布局。 $ {whenEmpty} - 当内部布局产生空结果时输出替代布局。 $ {WrapLine} - 在指定的行长度处包装另一个布局输出的结果。 $ {xml-encode} - 将另一个布局输出的结果转换为XML兼容。 NLog.Extended软件包 $ {appsetting} - 应用程序配置设置。 NLog.Web包 $ {aspnet-MVC-Action} - ASP.NET MVC动作名称 $ {aspnet-MVC-Controller} - ASP.NET MVC控制器名称 $ {aspnet-Application} - ASP.NET应用程序变量。 $ {aspnet-Item} - ASP.NET HttpContext项目变量。 $ {aspnet-TraceIdentifier} - ASP.NET跟踪标识符 $ {aspnet-Request} - ASP.NET请求变量。 $ {aspnet-Request-Cookie} - ASP.NET请求cookie内容。 $ {aspnet-Request-Host} - ASP.NET请求主机。 $ {aspnet-Request-Method} - ASP.NET请求方法(GET,POST等)。 $ {aspnet-Request-IP} - 客户端IP。 $ {aspnet-Request-QueryString} - ASP.NET请求查询字符串。 $ {aspnet-Request-Referrer} - ASP.NET请求引用者。 $ {aspnet-Request-UserAgent} - ASP.NET请求useragent。 $ {aspnet-Request-Url} - ASP.NET请求URL。 $ {aspnet-Session} - ASP.NET Session变量。 $ {aspnet-SessionId} - ASP.NET会话ID变量。 $ {aspnet-User-isAuthenticated} - ASP.NET用户身份验证? $ {aspnet-User-AuthType} - ASP.NET用户身份验证。 $ {aspnet-User-Identity} - ASP.NET用户变量。 $ {iis-site-name} - IIS站点名称。 外包装 外部软件包,不由NLog团队维护。 $ {xml} - 转换为XML格式 $ {gelf} - 将日志转换为GELF格式。
将自定义值传递给布局
即使布局渲染器提供了许多预定义的值,但您可能需要将特定于应用程序的值传递给布局。您可以通过向事件添加自定义属性来在代码中传递自己的值。然后使用$ {event-properties}渲染器检索值。
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://*.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方法是通过在线程上抛异常来终止线程的,这样可能会产生一些意想不到的问题。最好的办法是在启动的线程中加信号灯,当想要终止线程执行时就更改信号灯的状态,启动的线程当读到信号灯状态改变后自己结束代码的执行,这才是最安全的做法。