您的位置:首页 > 编程语言 > C#

CSharp 相关知识点小结

2016-12-20 09:59 519 查看
1.JS获取iframe下面的内容
document.getElementById('IFRAME1').contentDocument;

2.dialog 弹出层,定位:postion:'bottom',['right','bottom'],['left','bottom'].

3.IIS上部署WCF; 调用wcf或webapii一定要做安全认证。

cd d:

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319

aspnet_regiis.exe -i



4.项目之间如何调用WCF,怎么调试? 比如A项目,调用B项目的wcf服务。
a.先把B项目的wcf部署到IIS上,具体怎么部署? 看上面的3
b.在A项目引用B项目部署在IIS上的地址。
c.在B项目中,把IIS的wcf附加到进程,打断点。
d.运行A项目,打断点调试。

写wcf执行的时候,可以作为启动想,选择特定的页为wcf文件,就可以直接输入参数,点击执行,返回执行结果。

5.
string a="1";
if (!a.IsNullOrEmpty())
{
//这种写法第一次看到,其实差不多。
}
if(!string.IsNullOrEmpty(a))
{

}

6.添加wcf可能报错,需要按如下图设置:



7.6.mysql 中可以用,Show Create Table '表名',然后按F8,把创建脚步的语句拷贝出来。

8.用mysql客户端工具SQLyog,导入脚步,Tools -> Execute sql script.

9.redis 缓存,需要安装一个软件,一般情况下不需要做数据的持久化。

10.WCF 修改类具体实现的代码,引用WCF不需要更新,前提是方法名和参数名称没有改。

12.webAPI POSt处理SON数组:(后台是继承的属性,一定要用JSON.stringify,不然解析不了),而且前端只能穿一个参数,不然就会报500错误。get请求就没这个限制。

前端代码:

var mfItemStr = JSON.stringify({ mfItemStr: [{ "CreateId":1, "CreateName": "test1"},{ "CreateId":2, "CreateName": "test2"},{ "CreateId":3, "CreateName": "test3"}]});
$.ajax({
url: "/Test/Update",
type: "post",
dataType: "json",
contentType: "application/json",
data: mfItemStr,
success: function (data) {
console.log(data);
alert("Ok");
}
})


CSharp代码:

[HttpPost]
public HttpResponseMessage Update(JObject recordsSr)
{
var errMsg = new M_APIError();

try
{
if(recordsSr == null)
{
errMsg.ErrorCode = -1;
errMsg.Message = "recordsSr不能为空";
return Json.toJson(errMsg);
}

var str = recordsSr.ToObject<M_MFItem>();

if (str == null || str.mfItemStr == null || str.mfItemStr.Count <= 0)
{
errMsg.ErrorCode = -1;
errMsg.Message = "已选择的会员特性不能为空";
return Json.toJson(errMsg);
}

//已选择的会员特性
var records = str.mfItemStr;
int patientId = records.Select(t=>t.PatientID).First();
if (patientId <= 0)
{
errMsg.ErrorCode = -1;
errMsg.Message = "会员Id不能为空";
return Json.toJson(errMsg);
}

//获取当前会员的特性记录
var exists = new List<M_MemberFeaturesRecord>();
AspectF.Define.LogAPI(false).Do(() => exists = bll.GetMemberFeaturesRecordByPatientID(patientId));

if (exists == null && exists.Count <= 0)
{
errMsg.ErrorCode = -4;
errMsg.Message = "当前会员的特性记录为空";
}
else
{
//待新增记录(获取选中的记录不在当前会员的特性记录中的数据)
var adds = records.Where(c => !exists.Any(e => e.MFItemID == c.MFItemID)).ToList();

//给当前的特性记录加上特性名称,创建人和创建名称
exists.ForEach(t =>
{
var b = records.Where(a => a.MFItemID == t.MFItemID).FirstOrDefault();
if (b != null)
{
if (!string.IsNullOrWhiteSpace(b.MFItemName))
{
t.MFItemName = b.MFItemName;
}
if (b.CreateID > 0)
{
t.CreateID = b.CreateID;
}
if (!string.IsNullOrWhiteSpace(b.CreateName))
{
t.CreateName = b.CreateName;
}
}
});

//待删除记录
var deletes = exists.Where(c => !records.Any(e => e.MFItemID == c.MFItemID)).ToList();

//新增
var addResult = 0;
if (adds != null && adds.Count > 0)
{
AspectF.Define.LogAPI(false).Do(() => addResult = bll.BatchInsertMemberFeaturesRecord(adds));

if (addResult > 0)
{
AddmFRecordLog(patientId, adds, 1);
}
}

//删除
List<int> delList = new List<int>();
bool delResult = false;
if (deletes != null && deletes.Count > 0)
{
string recordIdStr = string.Join(",", deletes);

if (!string.IsNullOrWhiteSpace(recordIdStr))
{
AspectF.Define.LogAPI(false).Do(() => delResult = bll.BatchDeleteMemberFeaturesRecord(recordIdStr));
if (delResult)
{
AddmFRecordLog(patientId, deletes, 2);
}
}
}

if (addResult > 0 && delResult)
{
errMsg.ErrorCode = 0;
errMsg.Message = "成功";
errMsg.ReturnData = addResult;
}
else
{
errMsg.ErrorCode = -5;
errMsg.Message = "失败";
}
}

}
catch (Exception ex)
{
errMsg.ErrorCode = 500;
errMsg.Message = ex.Message;
}
return Json.toJson(errMsg);
}


13.ADO.NET 执行批量Sql server 的SQL,而mysql不支持,只能把批量的MySQL写在存储过程里面,然后调用。

sql server:

declare  @result int;
set @result=-1092
if exists(select top 1 1 from [Order] a where A.OrderCurrentStatus=1 and A.Code=@Code)
begin
update [Order] set OrderCurrentStatus=2,OrderType=0 where Code=@Code;
--插入日志
INSERT INTO [OrderTrans]
([OrderId],[TransType],[OrderType],[OrderCode],
[IsResult],[Creater],[CreateDate],[Remark],[BusCode])
SELECT 0,3,0,@code,1,@Creater,GETDATE(),
'邮费订单审核',@code
set @result=@@error;
end
else
begin
set @result=1091
end
select @result;


14.h5增加类jquery

document.querySelector(".")

15.优化mysql的SQL,可以用explain,

EXPLAIN SELECT * FROM `accounts`


16.调试Wcf 和webAPI

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WcfTestClient.exe 调试调用WCF

调试webapi:

1).可以在chrome 添加插件Postman-REST-Client_v0.8.1

2).下载PC版 Postman-win64-5.0.0-Setup.exe https://download4os.com/postman-4-10-3-60258/

3).firefox 添加插件 httprequester

4).jmeter 参考地址: http://jingyan.baidu.com/article/14bd256e7e707cbb6d2612cf.html?qq-pf-to=pcqq.c2c

17.MySQL数据库表字段生成对应的实体:

每个表生成实体类型,如果表字段很多的话,一个一个写很浪费时间,可以用正则(或动软代码生成器)来处理,正则步骤如下:

1.从MySQL中查询的信息中拿到createTable数据;SHOW CREATE TABLE sys_test
2.通过以下正则来替换
`(\S+)`\s+(\S+).*'(.*)',

\t\t\/\/\/<summary>\n\t\t\/\/\/\t\3\n\t\t\/\/\/</summary>\n\t\t\[DataMember\]\n\t\tpublic \2 \1 \{ get; set;\}\n
通过正则之后,可以将table信息统一变成这种格式:
/// <summary>
///     是否接受短信:0-否,1-是
/// </summary>
[DataMember]
public sbyte IsAcceptSMS { get; set; }
3.整理一些类型 ,int\(\d+\)-->int  int\(\d+\)
nvarchar\(\d+\)/text/char/varchar\(\d+\)--->string
tinyint --->sbyte
date/datetime --->DateTime
time ---> TimeSpan
bigint-->long
smallint ->short
int(11) unsigned -> uint
double -> double
bit -> bool
decimal -> decimal
blob -> byte[]
float-> float

(\S+)
sInfo\.\1 = info\.\1;

info\.\1 = sInfo\.\1;

\s+

Creator,
CreateTime,
TestLen,
OrderTest,
PlayAmount

先把,逗号替换掉,然后用(\S+)替换成sInfo\.\1 = info\.\1;

注意:可空的上面的正则处理不了。处理方法: 非空类型没有勾选(或为DEFAULT NULL),C#定义需要可空类型。比如 tinyint 对 sbyte? 也可以通过Show full fields from TableA 看的Null列是否为YES,为YES就加?(字符串类型的不用加)

去掉换行:\s+ 替换为空格

18.uwp(Windows 10开发)

之前用到http://stackoverflow.com/questions/17049677/how-do-i-print-webview-content-in-a-windows-store-app 这个方法还是不行,因为我要打印曲线图。

a.打印页面,分页的方法:https://msdn.microsoft.com/zh-cn/library/windows/apps/xaml/hh465204

代码:https://code.msdn.microsoft.com/windowsapps/Print-Sample-c544cce6

b.打印webview嵌入html页面所有内容的方法(启动程序,打开谷歌浏览器,采用window.print打印):

CSharp代码:

/// <summary>
/// 打印功能
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void ButtonPrint_Click(object sender, RoutedEventArgs e)
{
try
{
await SaveFileAsync(@"Report\jscript\data.js", "var jsonData = " + jsonData);
await LaunchFileAsync(@"Report\html\ReportDetail.html");
}
catch (Exception ex)
{
await new MessageDialog("打印失败").ShowAsync();
}
}

/// <summary>
/// 保存文件
/// </summary>
/// <param name="filePath">相对于localfilepath</param>
/// <param name="contents">内容</param>
/// <param name="options">选项m</param>
/// <returns></returns>
public static async Task SaveFileAsync(string filePath,string contents,CreationCollisionOption options= CreationCollisionOption.ReplaceExisting)
{
try
{
var localFolder = ApplicationData.Current.LocalFolder;
var file = await localFolder.CreateFileAsync(filePath, options);
await FileIO.AppendTextAsync(file, contents);
}
catch (Exception ex)
{
await FileLoger.WriteLog("savefile Error",ex,filePath);
}
}

/// <summary>
/// launch file
/// </summary>
/// <param name="filePath">相对于localfilepath</param>
/// <returns></returns>
public static async Task LaunchFileAsync(string filePath)
{
var localFolder = ApplicationData.Current.LocalFolder;
var file = await localFolder.CreateFileAsync(filePath, CreationCollisionOption.OpenIfExists);
await Windows.System.Launcher.LaunchFileAsync(file);
}


JS:方法

function ExecutePrint() {
setTimeout(function () {
if ($.browser.mozilla) {
document.getElementById("WebBrowserObj").execWB(7, 1);
}
else {
window.print();
}
}, 3000);
}

$(function () {
LoadData(jsonData);
ExecutePrint();
});


19. (1). mysql 可以利用GROUP_CONCAT把个值拼接在一起,默认以分号相隔。也可以指定其分隔符号。

GROUP_CONCAT(DISTINCT Guardian SEPARATOR ';') Guardian 以分号显示“a;b;c”

(2).mysql类型为time类型的时候,对应的C#定义为TimeSpan,赋值如下:

DateTime dt = DateTime.Parse("2016-6-29 19:20:30");
TimeSpan times = dt.TimeOfDay;//注意这里赋值

或
var tt = 490;
var ss = TimeSpan.FromMinutes(tt);


(3).C# 执行mysql脚本可以这样一起写:

INSERT INTO sys_log(`PatientID`,`MFItemID`,`MFItemName`,`CreateID`,`CreateName`,
`UpdateID`,`CreateTime`,`UpdateTime`,`DoctorID`,`DoctorName`,`DrID`,`DrName`,`OperationType`,`Remark`,`CARecordID`)
SELECT @NewPatientID,`MFItemID`,`MFItemName`,`CreateID`,`CreateName`,`UpdateID`,`CreateTime`,`UpdateTime`,`DoctorID`,`DoctorName`,`DrID`,`DrName`,`OperationType`,`Remark`,@RecordId
FROM sys_log WHERE `RecordLogID`=@RecordLogID;


(4).用CONCAT拼接字符串 LIKE CONCAT('%',@Title,'%')

(5).mysql获取自增的列的方法:区别可以参考:MYSQL LAST_INSERT_ID() 自增列详解MySQL获取自增主键ID的四种方法

SELECT @@IDENTITY;
SELECT LAST_INSERT_ID();


(6).写方法,尽量使用参数,而不用直接传值,防止SQL注入,参数化安全性高些。 比如select * from A where id in(1,2,3),可以select * from A where 1= 1 and (id=1 or id =2 or id=3) 。具体如下(注意红色标注的代码):

public List<M_MTest> GetTetItemIds(int[] itemId)
{
if (itemId == null || itemId.Length < 1) return null;
const string sqlText = @"select * from Test where MFItemID=@ItemId";
var where = new StringBuilder(30, 30 * itemId.Length);
var param = new List<MySqlParameter>();
where.Append(" AND ");
if (itemId.Length == 1)
{
where.Append("MFItemID=@ItemId ");
param.Add(new MySqlParameter("@ItemId", itemId[0]));
}
else
{
where.Append("( ");
for (var i = 0; i < itemId.Length; i++)
{
where.Append("MFItemID=@ItemId");
where.Append(i);
if (i < itemId.Length - 1)
{
where.Append(" OR ");
}
param.Add(new MySqlParameter("@ItemId" + i, itemId[i]));
}
where.Append(" )");
}
var result = MySqlHelper.ExecuteDataTable(
MySqlHelper.ConnectionStringRemp,
CommandType.Text,
sqlText + @where,
param.ToArray()
);
return result.ConvertToList<M_MTest>();
}


int[] orgId;
const string sql =
"SELECT `MFTypeID`,`MFTypeName`,`MFTypeParentID`,`MFTypePath`,`MFTypeLevel`,`MFTypeOrder`,`Description`,`IsSystem`,`IsPushApp`,`IsDeleted`,`OrgID`,`CreateID`,`CreateTime`,`UpdateID`,`UpdateTime`,IFNULL((SELECT MFTypeID FROM sys_memberfeaturestype WHERE MFTypeParentID = s.MFTypeID limit 0,1),0) IsHasSub  FROM sys_memberfeaturestype s where MFTypeParentID != -1 AND IsDeleted = 0";
var where = new StringBuilder();
var param = new List<MySqlParameter>();
if (orgId != null && orgId.Any())
{
if (orgId.Length == 1)
{
where.Append(" AND (OrgID = @OrgId OR OrgID = 0)");
param.Add(new MySqlParameter("@OrgId", orgId[0]));
}
else
{
where.Append(" AND ( OrgID = 0");
for (var i = 0; i < orgId.Length; i++)
{
where.Append(" OR");
where.Append(" OrgID = @OrgId");
where.Append(i);
param.Add(new MySqlParameter("@OrgId" + i, orgId[i]));
}
where.Append(" )");
}
}


(7).mysql 批量新增:insert into Test(Id,name) value(1,"t"),(2,"test");

/// <summary>
///批量新增
/// </summary>
/// <param name="listTest">集合</param>
/// <returns></returns>
public int BatchInsertTEst(List<M_Test> listTest)
{
if (listTest == null || listTest.Count <= 0)
{
LogHelper.AddErrorLog("没有记录", "", "");
return -1;
}

var strSql =
new StringBuilder(
"INSERT INTO sys_Test(`PatientID`,`MFItemID`,`CreateID`,`CreateTime`) ");

var mysqlParam = new List<MySqlParameter>();
for (var i = 0; i < listTest.Count; i++)
{
var item = listTest[i];
if (i == 0)
{
strSql.AppendFormat(" VALUES(@PatientID{0},@MFItemID{0},@CreateID{0},@CreateTime{0})", i);
}
if (i > 0)
{
strSql.AppendFormat(",(@PatientID{0},@MFItemID{0},@CreateID{0},@CreateTime{0})", i);
}
mysqlParam.Add(new MySqlParameter(string.Format("@PatientID{0}", i), item.PatientID));
mysqlParam.Add(new MySqlParameter(string.Format("@MFItemID{0}", i), item.MFItemID));
mysqlParam.Add(new MySqlParameter(string.Format("@CreateID{0}", i), item.CreateID));
mysqlParam.Add(new MySqlParameter(string.Format("@CreateTime{0}", i), item.CreateTime));
}

try
{
var num = MySqlHelper.ExecuteNonQuery(MySqlHelper.connectionStringRemp, CommandType.Text,
strSql.ToString(), mysqlParam.ToArray());

return num;
}
catch (Exception ex)
{
LogHelper.AddErrorLog("批量新增失败", ex.ToString(), "");
return 0;
}
}


注意:这里没考虑大数据的问题,如一次性插入10万数据,就不能这样处理。 可以通过多线程的方式,每次给DB中添加1000条,另外的话还需要加上事务。可以参考下面的代码:

//设置CPU给当前应用程序分配的最小线程数
System.Threading.ThreadPool.SetMinThreads(100, 100);
var list = new List<Task>();
var count = 10000*10000;//1千万条
var num = 1000;//每次循环条数
for (int j = 0; j < count; j++)
{
//每次1000条数据
for (int i = 0; i < num; i++)
{
var result = Task.Run(() =>
{
//插入DB
});
list.Add(result);
}
//等待1000个线程跑完
Task.WaitAll(list.ToArray());
count = count - num;
}


(8).批量修改:

/// <summary>
///     批量修改
/// </summary>
/// <param name="listmfRecordlog"></param>
/// <returns>是否成功</returns>
public bool BatchUpdateTest(List<M_Test> listTest)
{
var strSql = new StringBuilder();
var mysqlParam = new List<MySqlParameter>();

for (var i = 0; i < listTest.Count; i++)
{
var item = listTest[i];
strSql.AppendFormat(
"UPDATE sys_Test SET UpdateName = @UpdateName{0},UpdateTime=@UpdateTime{0},UpdateID=@UpdateID{0},OperationType=@OperationType{0} WHERE RecordLogID=@RecordLogID{0};",
i);
mysqlParam.Add(new MySqlParameter(string.Format("@UpdateName{0}", i), item.UpdateName));
mysqlParam.Add(new MySqlParameter(string.Format("@UpdateTime{0}", i), item.UpdateTime));
mysqlParam.Add(new MySqlParameter(string.Format("@UpdateID{0}", i), item.UpdateID));
mysqlParam.Add(new MySqlParameter(string.Format("@OperationType{0}", i), item.OperationType));
mysqlParam.Add(new MySqlParameter(string.Format("@CreateName{0}", i), item.CreateName));
mysqlParam.Add(new MySqlParameter(string.Format("@RecordLogID{0}", i), item.RecordLogID));
}

try
{
var num = MySqlHelper.ExecuteNonQuery(MySqlHelper.ConnectionStringRemp, CommandType.Text,
strSql.ToString(), mysqlParam.ToArray());

return num > 0;
}
catch (Exception ex)
{
LogHelper.AddErrorLog("批量修改失败", ex.ToString(), "");
return false;
}
}


(9).拼接SQL别用where 1=1,然后再拼接and

var where = new StringBuilder();
where.Append(where.Length > 1 ? " AND" : " WHERE")

20.SQL里面如果排序不了,可以多利用linq 或lamber表达式排序。

21.前端JS通过数组,传一个对象给ASP.net MVC 的后台方法。后台定义一个实体类和前端的名称一致,Mvc会自动转化。

JS代码:

function btnSave() {
var btnSave = document.getElementById("btnSave");
//将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
btnSave.disabled = true;

if ($("#Remark").val() == "") {
alert("备注不能为空");
btnSave.disabled = false;
return false;
}
var data = {};
data["data.CallStatus"] = $("#CallStatus").val();
data["data.ITime"] = $("#ITime").val();
data["data.Remark"] = $("#Remark").val();
data["data.IResult"] = $("#IResult").val();

$.ajax({
type: 'post',
url: "/TestWeb/TestActivity/TestDetail",
datatype: 'json',//返回json格式的数据
data: data,
error: function (XHR) {
alert('网络异常,请稍候再试');
btnSave.disabled = false;
},
success: function (data) {
if (data.Success) {
alert("添加成功");

} else {
alert("添加失败");
}
}
});
}


C#代码:

[HttpPost]
public JsonResult TestDetail(M_TestDetail data)//这里data要和前端的data["data.CallStatus"] 中括号里面的data名称一样,对应的字段名该实体类字段名称一样。MVC会自动转化
{
var msg = new ResultMsgInfo();
msg.Msg = "保存成功";
msg.Success = true;
return Json(msg, JsonRequestBehavior.AllowGet);
}


M_TestDetail实体类:

[DataContract]
public class M_TestDetail
{
///<summary>
///    邀约电话接通情况:0 接听成功 1 无人接听 2 拒接 3 信息错误 4 空号 5 号码过期 6 未接通 7 通话中
///</summary>
[DataMember]
public sbyte? CallStatus { get; set; }

///<summary>
///    同意到场时间
///</summary>
[DataMember]
public string ITime { get; set; }

///<summary>
///    备注
///</summary>
[DataMember]
public string Remark { get; set; }

///<summary>
///    邀约结果:0 无 1 来 2 不来 3 待定 4 重新邀约
///</summary>
[DataMember]
public sbyte? IResult { get; set; }
}


22.Json转换实体,使用 Deserialize<M_TestDetail>(jsonData); 需要引入Newtonsoft.Json.dll

public T Deserialize<T>(string json)
{
T obj = Activator.CreateInstance<T>();
var result = JsonConvert.DeserializeObject<T>(json);
return result;
}


23.ASP.Net MVC

(1).页面判断,里面的文本需要加<text></text>,如下:

<input type="checkbox" @if (dateAm != null && dateAm.Count > 0) {<text> checked="checked"</text> }/>


(2). Html.RenderAction的使用

cshtml 代码:

@{Html.RenderAction("JudgementStatus", new { num = item.CallStatus, statusName = "CallStatus" });}


控制器的C#代码:

/// <summary>
/// 获取状态描述
/// </summary>
/// <param name="num"></param>
/// <param name="statusName"></param>
/// <returns></returns>
public string JudgementStatus(sbyte? num, string statusName)
{
var str = string.Empty;
switch (statusName)
{
case "CallStatus":
if (num.HasValue)
{
switch (num.Value)
{
//0 接听成功 1 无人接听 2 信息错误 3 拒接 4 空号 5 号码过期 6 未接通 7 通话中
case 0: str = "接听成功"; break;
case 1: str = "无人接听"; break;
case 2: str = "拒接"; break;
case 3: str = "信息错误"; break;
case 4: str = "空号"; break;
case 5: str = "号码过期"; break;
case 6: str = "未接通"; break;
case 7: str = "通话中"; break;
default: str = ""; break;
}
}
else
{
str = ""; break;
}
break;
case "IsSign":
if (num.HasValue)
{
switch (num.Value)
{
case 0: str = "未到场"; break;
case 1: str = "已到场"; break;
default: str = ""; break;
}
}
else
{
str = "未到场"; break;
}
break;
}
return str;
}


24.时间处理的时候,不要用js的toLocaleDateString(); 因为兼容性不好,还要考虑到服务器后台解析的兼容性,在Microsoft Edge序列化数组的时候,传到后台mvc,反序列化DataTime直接报错,而且把datatime改成string,然后通过Convert.ToDateTime("2016-8-29")转化不了,原因是编码的问题,当我把2016-8-29拷贝到记事本里面保存,然后重新打开直接出现?。可以改成拼接的写法:

var start = new Date($("#StartDate").val());
new Date(start).toLocaleDateString();

上面的写法改成如下:
var month = new Date(start).getMonth() + 1;
var datatostring = new Date(start).getFullYear() + "-" + month + "-" + new Date(start).getDate();

var _oneDay = new Date(start.setDate(start.getDate() + 1));
var month = new Date(_oneDay).getMonth() + 1;
var datatostring = new Date(start).getFullYear() + "-" + month + "-" + new Date(start).getDate();

IE10出现兼容性可以用下面的方法处理:
.replace("年", "/").replace("月", "/").replace("日", "").replace(/\?/g, "");
.replace("-", "/")
replace("/", "-")


25.JS: var re = /^[0-9]*[1-9][0-9]*$/;  //正整数

.replace(/\?/g, "");去掉?

26.展示mysql变量的函数 SHOW VARIABLES LIKE '%skip%';

27.C#访问本地mysql出现“ HOST 'test' IS NOT allowed TO connect TO this MySQL server” ?

解决方法:(1).如下图 (2).找到安排目录的C:\Program Files\MySQL\MySQL Server 5.5\my.ini,打开my.ini,加上skip_name_resolve=1,重启mysql服务。





28.jQuery 可以通过commitForm提交表单,mvc接受值,建议使用FormCollection取值,不要使用request取值

<form id="f1" method="POST">
<h2>AddAddress</h2>
<input type="text" name="Address"/>
<input type="text" name="Name"/>
<input id="Submit1" type="submit" value="submit"/>
</form>
<script type="text/javascript">
$(function() {
$("#f1").commitForm({
url: '/home/test',
callBack:function(data) {
alert(data);
}
});
});
</script>


29.大数据并发出来:a.负载均衡(建多个站点,nginx(参考https://lufficc.com/blog/configure-nginx-as-a-web-server) ) b.使用缓存

30.数据的同步可以通过Quartz.net 写job处理,需要按时间来升序,需要考虑到相同时间的数据。

31.mysql 调用存储过程

SET @iDrID=2;
SET @vPatientName='';
SET @vSchemeTitle='';
SET @dSCreateTime='';
SET @dECreateTime='';
SET @iCheckSuggestFlag=-1;
SET @iCurrentPageIndex=0;
SET @iPageSize=10;
CALL proc_Scheme_QueryList(@iDrID,@vPatientName,@vSchemeTitle,@dSCreateTime,@dECreateTime,@iCheckSuggestFlag,@iCurrentPageIndex,@iPageSize,@iRowCount);
SELECT @iRowCount;


32.C#发送http 请求:1.HttpWebRequest 2.HttpClient(webapi)

33.直接返回某列的list集合

public List<int> GetAlltestIds()
{
const string sql = " select testId from sys_test  ";

var ds = MySqlHelper.ExecuteDataSet(ConnectionStringConfig.DataCenter, CommandType.Text, sql, new MySqlParameter[] { });

var list = ds.Tables[0].Rows.Cast<object>().Select((r, i) => Convert.ToInt32(ds.Tables[0].Rows[i][0])).ToList();

return list;
}


34.通过ASP.MVC自带的传参数到后台进行新增

public ActionResult Register()
{
var vmodel = new M_UserTest();
return View(vmodel);
}

public ActionResult RegisterTest(M_UserTest data)
{
var result = bll.Add(data);
return View();
}


@using Model
@model M_UserTest
@{
ViewBag.Title = "Register";
}

<h2>Register</h2>
<div class="row">
<div class="col-md-8">
<section id="loginForm">
@using (Html.BeginForm("RegisterTest", "Home", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
<div class="form-group">
<label class="col-md-2 control-label">用户名</label>
<div class="col-md-10">
@Html.TextBoxFor(m => m.username, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">账号</label>
<div class="col-md-10">
@Html.TextBoxFor(m => m.userAccount, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">密码</label>
<div class="col-md-10">
@Html.PasswordFor(m => m.userPwd, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="注册" class="btn btn-default" />
</div>
</div>
}
</section>
</div>
</div>


35.MySQL修改字段默认值和修改字段长度

use `test_ch`;
/*修改字段默认值*/
alter table hm_test modify AuditStatus tinyint not null default 1 comment '审核状态 0.未审核,1.已审核';
/*修改字段长度*/
alter table hm_test modify column Summary varchar(2000);


36.C#把字符串数组转化成List

/// <summary>
/// 把字符串数组转化成List
/// </summary>
/// <param name="target">字符串</param>
/// <returns></returns>
public static List<int> AsList(this string[] target)
{
var arr = new List<int>();
if (target == null || target.Length == 0) return arr;
Array.ForEach(target, id =>
{
int tmpId;
if (int.TryParse(id, out tmpId))
{
arr.Add(tmpId);
}
});
return arr;
}


string scGoodIds = "1,2,,3,4,5,6,7";
var ids = scGoodIds.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).AsList();


37.用EF写出一条分页语句,页码数是1,页大学为20. 可参考LINQ系列:LINQ to SQL Take/Skip

pageIndex PageSize

var reulst = (from u in uList
orderby u.toolingNo
select u).Skip(pageSize *(pageIndex -1)).Take(pageSize);

OrderBy 是排序(后面是条件)然后要查询所有的,在所有的数据中在查询你要分页的数据,skip是在分页在前有多少条数据,也就是在当前页数据之前的数据总和,(跳过序列中指定数量的元素,然后返回剩余的元素。)pageSize*(pageIndex-1),Take 是返回多少条数据,也就是pageSize!

38.ling分组,处理

var IaidList = times.GroupBy(p => p.IAId).ToDictionary(p => p.Key, r => r.Select(o => o)).OrderBy(p => p.Key).ToList();


2)linq 分组去除重复的某项

var result = testItem.GroupBy(t => t.TestItemCode).Select(t => t.OrderByDescending(p => p.CreatedTime).OrderByDescending(p => p.TestItemID).FirstOrDefault());


3).分组汇总

q = q.GroupBy(t => t.CreateDate).Select(g => new TestData
{
CreateDate = g.Key,
Num = g.Sum(p => p.Num),
});


39.Quartz.net 安装服务和卸载服务

安装服务:

@Test.exe install
@pause
@exit


保存记事本里面,后缀名为.bat

卸载服务:

@Test.exe uninstall
@net start Test
@pause
@exit


40.C# 对象转jSON 时 过滤 NULL 的属性 参考:https://q.cnblogs.com/q/72031/ http://www.newtonsoft.com/json/help/html/ReducingSerializedJSONSize.htm 需要引用Newtonsoft.Json.dll

public class Person
{
public int Id { get; set; }

public string Name { get; set; }
}


static void Main(string[] args)
{
var list = new List<Person>();

for (int i = 1; i < 5; i++)
{

list.Add(new Person()
{
Id = i,
Name = "test" + i
});
}

list.Add(new Person()
{
Id = 5,
Name = null,
});

string ignored = JsonConvert.SerializeObject(list, Formatting.Indented, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
//[{"Id":1,"Name":"test1"},{"Id":2,"Name":"test2"},{"Id":3,"Name":"test3"},{"Id":4,"Name":"test4"},{"Id":5}]

var test = JsonConvert.DeserializeObject<List<Person>>(ignored);

Console.ReadLine();
}


41.怎么监控EF生成的sql

1).EntityFramework Profiler, 下载地址:https://hibernatingrhinos.com/products/EFProf

2). 如果是SQL server 可以用SQL Server Profiler, 具体可以参考:http://www.cnblogs.com/allenhua/p/3533975.html

42.去掉webapi的token验证。在compilation 家debug="true" 。 <compilation debug="true" targetFramework="4.5" />

43. IIS初始化(预加载),解决第一次访问慢,程序池被回收问题

44.计算时间

Stopwatch stopwatch = new Stopwatch();
//第一次计时
stopwatch.Start();
Console.WriteLine("Stopwatch is running:{0}",stopwatch.IsRunning);//判断当前Stopwatch的状态
System.Threading.Thread.Sleep(1000);//耗时操作
stopwatch.Stop();
Console.WriteLine("Using Elapsed output runTime:{0}", stopwatch.Elapsed.ToString());//这里使用时间差来输出
Console.WriteLine("Using ElapsedMilliseconds output runTime:{0}", stopwatch.ElapsedMilliseconds);//这里面使用毫秒来输出


45.调用数据库或服务,一定要释放。 可以通过查看oracle的连接数来看是否是否资源 select count(*) from v$session;

1).单个写

using (testService as IDisposable)
{
persont = testService.GetTest(name);
}


2).在基类写,实现IDisposable。

private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing && _context != null)
{
_context.Dispose();
}
}
this.disposed = true;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}


46. EF 修改数据出现:Attaching an entity of type 'HR_TEST' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

原先代码:

public bool Update(TEntity entity)
{
_context.Entry<TEntity>(entity).State = EntityState.Modified;
return _context.SaveChanges() > 0;
}


改成:

public bool Update(TEntity entity, Func<TEntity, int> getKey)
{
// Retreive the Id through reflection

var entry = _context.Entry<TEntity>(entity);
if (entry.State == EntityState.Detached)
{
var set = _context.Set<TEntity>();
TEntity attachedEntity = set.Find(getKey(entity));  // access the key
if (attachedEntity != null)
{
var attachedEntry = _context.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(entity);
AttachedEntry.State = EntityState.Modified;
}
else
{
set.Attach(entity);
entry.State = EntityState.Modified; // attach the entity
}
}

return _context.SaveChanges() > 0;
}


47.可以用action定义实体转化

//定义动态映射函数
Action<Patient> action = (Patient member) =>
{
person.Name = member.Name;
person.Gender = member.Sex;
person.BirthDate = !string.IsNullOrWhiteSpace(member.Birthday) ? member.Birthday.Replace("-", "") : person.BirthDate;//系统中的生日全部是yyyyMMdd格式
person.Nationality = member.Ethnic;
person.CensusAddressName = member.Domicile;
person.Country = country;
person.IDNumber = idcard;
person.IDType = idType;
};


48.C#生成随机流水号:

public static string GenerateOrderId()
{
string text = string.Empty;
System.Random random = new System.Random();
for (int i = 0; i < 7; i++)
{
int num = random.Next();
text += ((char)(48 + (ushort)(num % 10))).ToString();
}
return System.DateTime.Now.ToString("yyyyMMdd") + text;
}


49.redis加入到Windows 服务

安装命令:

redis-server.exe --service-install redis.windows.conf --loglevel verbose
卸载命令:
redis-server --service-uninstall

50.异步调用

1).

Task.Run(() =>
{
Test();
});


2).

Action act = () => Test();
act.BeginInvoke(t => act.EndInvoke(t), null);


51.C# 调用webApi

1).webpai Post

[Route("CheckUp"), HttpPost]
public IHttpActionResult CheckUp(CheckUp request)
{
return Ok(new { Status = 0, Msg = "" });
}


调用代码

/// <summary>
///  需要引用 System.Net.dll,System.IO.dll
/// </summary>
/// <param name="url">url</param>
/// <param name="headers">头文信息</param>
/// <param name="format">格式</param>
/// <param name="formData">传入数据格式</param>
/// <returns></returns>
public static string Post(string url, Dictionary<string, string> headers, string format, string formData)
{
byte[] postData = Encoding.UTF8.GetBytes(formData);

HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.AllowAutoRedirect = false;
request.ContentType = format+";charset=utf-8";
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)";
if (headers != null)
{
foreach (KeyValuePair<string, string> item in headers)
{
request.Headers.Add(item.Key, item.Value);
}
}

request.ContentLength = postData.Length;
// 开始请求
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(postData, 0, postData.Length);
}

HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream s = response.GetResponseStream();
StreamReader reader = new StreamReader(s, Encoding.GetEncoding("UTF-8"));
string result = reader.ReadToEnd();
reader.Close();
s.Close();
if (response != null)
response.Close();
if (request != null)
request.Abort();
return result;
}
Post(url, new Dictionary<string, string>(), "application/json", JsonConvert.SerializeObject(checckup));


//定义Request 并设置request的路径
WebRequest request = WebRequest.Create(url);
request.Method = "post";

//设置参数的编码格式,解决中文乱码
byte[] byteArray = Encoding.UTF8.GetBytes(data);

//设置Request的MINE类型及内容长度
request.ContentType = "application/json";
request.ContentLength = byteArray.Length;

//打开request字符流
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

//定义response为前面的request响应
WebResponse response = request.GetResponse();

//获取相应的状态代码
var str = ((HttpWebResponse)response).StatusCode;

//定义response字符流
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFormServer = reader.ReadToEnd();//读取所有


2).webapi

[Route("CheckUp"), HttpPost]
public IHttpActionResult CheckUp([FromBody] string baseRequest)
{
}


调用代码

//设置HttpClientHandler的AutomaticDecompression
var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };
//创建HttpClient(注意传入HttpClientHandler)
using (var http = new HttpClient(handler))
{
//使用FormUrlEncodedContent做HttpContent
var content = new FormUrlEncodedContent(new Dictionary<string, string>() {
{"",data}//键名必须为空,data为json字符串
});

//await异步等待回应

var response = await http.PostAsync(url, content);
//确保HTTP成功状态值
response.EnsureSuccessStatusCode();
//await异步读取最后的JSON(注意此时gzip已经被自动解压缩了,因为上面的AutomaticDecompression = DecompressionMethods.GZip)
await response.Content.ReadAsStringAsync();
}


52. C# async和await string 转为Task<string>

public static async Task<string> Test(string[] inputs)
{
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < 10; i++)
{
sBuilder.Append(i.ToString("x2"));
}
return await Task.FromResult(sBuilder.ToString());
}


53. 实体转化不用重新写方法,可以用委托(Action<T>)来实现,demo如下:

private void Test(PersonInfoModels data)
{

Action<PersonInfoModels> action = (PersonInfoModels m) =>
{
person.Name = m.Name;
}

if (data != null)
{
//调用
action(data);
}
}


54.Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式

当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据。需要使用Left Join获取数据:
Linq语法如下:
var sg = (from g in dc.sgroup
join gu in dc.sgroupuser on g.gKey equals gu.gKey into l
from lgu in l.DefaultIfEmpty()
select new { g, lgu }).ToList();
Lambda表达式如下:
var sg = dc.sgroup.GroupJoin(dc.sgroupuser, g => g.gKey, gu => gu.gKey, (g, gu) => new { g, gu }).Select(o=>o).ToList() ;
注意:
Linq 与Lambda表达式取出的结果有所不同.Linq取出的结果的记录数与Sql中的Left Join的结果相同,而Lambda表达式取出的记录数是sgroup表中的记录数,sgroupuser对应的记录是以对象集合存在于结果中
附:
下面是Inner Join:
Linq语法如下:
var sg = (from g in dc.sgroup
join gu in dc.sgroupuser on g.gKey equals gu.gKey
select new { g, gu }).ToList();
Lambda表达式如下:
var sg = dc.sgroup.Join(dc.sgroupuser, g => g.gKey, gu => gu.gKey, (g, gu) => new { g, gu }).Select(o=>o).ToList() ;
注意:
上面最后都用到了ToList()方法 , 用ToList()是为了一次性将数据取到本地

http://www.cnblogs.com/xinjian/archive/2010/11/17/1879959.html

55.

1).linq 实现left join,并在on 后面添加and

var list = from a in bloodlist join b in sugarlist on new { a.OrganizationID,a.MonitorDate } equals new { b.OrganizationID, b.MonitorDate } into sugarTemp
from newb in sugarTemp.DefaultIfEmpty()
select new DetectData {
OrganizationID = a.OrganizationID,
MonitorDate = a.MonitorDate,
DayBloodPressureNum = a.DayBloodPressureNum,
DaySugarPressureNum = newb != null ? newb.DaySugarPressureNum : 0
};


2).let

result = (from b in bloodlist
join s in sugarlist on new { b.OrganizationID, b.MonitorDate } equals new { s.OrganizationID, s.MonitorDate }
select new BI_IndexDetectData
{
MonitorDate = b.MonitorDate,
OrganizationID = b.OrganizationID,
DayBloodPressureNum = b.DayBloodPressureNum,
DaySugarPressureNum = s.DaySugarPressureNum,
}).ToList();
var result1 = (from b in bloodlist
join s in sugarlist on new { b.OrganizationID, b.MonitorDate } equals new { s.OrganizationID, s.MonitorDate }
let daySugarPressureNum = s.DaySugarPressureNum
where s.DaySugarPressureNum > 0
select new BI_IndexDetectData
{
MonitorDate = b.MonitorDate,
OrganizationID = b.OrganizationID,
DayBloodPressureNum = b.DayBloodPressureNum,
DaySugarPressureNum = daySugarPressureNum,
}).ToList();


56.C#递归根据日期分页获取所有满足条件的体检信息

调用 var dataresult = GetPageOfAllCheckUpRegInfo(pageIndex, pageSize, BeginCheckDate.Value, endCheckUpDate.Value,isVip);

#region 根据总检日期和页码获取所有满足条件的体检登记信息
/// <summary>
/// 根据总检日期和页码获取所有满足条件的体检登记信息
/// </summary>
/// <param name="pageIndex">当前页码</param>
/// <param name="pageSize">页大小</param>
/// <param name="bcheckUpDate">总检开始日期</param>
/// <param name="echeckUpDate">总检结束日期</param>
/// <returns></returns>
private List<CheckUpRegInfo> GetPageOfAllCheckUpRegInfo(int pageIndex, int pageSize, DateTime bcheckUpDate, DateTime echeckUpDate, string isVip)
{
var result = new List<CheckUpRegInfo>();
// 递归获取所有满足条件的体检登记信息
GetAllCheckUpRegInfo(pageIndex, pageSize, bcheckUpDate, echeckUpDate,isVip,result);
return result;
}
#endregion

#region 递归获取体检登记信息
/// <summary>
/// 递归调用
/// </summary>
/// <param name="pageIndex">当前页码</param>
/// <param name="pageSize">页大小</param>
/// <param name="bcheckUpDate">总检开始日期</param>
/// <param name="echeckUpDate">总检结束日期</param>
/// <param name="isVip">是否vip</param>
/// <param name="result">返回结果</param>
private void GetAllCheckUpRegInfo(int pageIndex, int pageSize, DateTime bcheckUpDate, DateTime echeckUpDate,string isVip,List<CheckUpRegInfo> result)
{
try
{
var req = new CheckUpDataInput();
req.BeginCheckDate = bcheckUpDate;
req.EndCheckDate = echeckUpDate;
req.PageSize = pageSize;
req.PageIndex = pageIndex;
req.SortType = false;
req.OrderBy = "JCRQ";//总检日期
req.IsVip = isVip;
CheckService = new AutoCheckService(req);
var dataResult = CheckService.GetPageOfCheckUpRegInfo();
//释放资源
using (CheckService as IDisposable) { }

if (dataResult != null && dataResult.ResultCode == 100)
{
var list = dataResult.Result.ToList();
if (list != null && list.Count > 0)
{
var PageCount = dataResult.PageCount;
//本页执行完成,继续执行下一页
if (pageIndex <= PageCount)
{
pageIndex++;
result.AddRange(list);
GetAllCheckUpRegInfo(pageIndex, pageSize, bcheckUpDate, echeckUpDate, isVip, result);
}
}
}
}
catch (Exception ex)
{
WriteLog("GetAllCheckUpRegInfo递归获取体检登记信息:" + ex.Message);
}
}
#endregion


57.将字符串转为int,否则返回默认值

/// <summary>
/// 将字符串转为int,否则返回默认值
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public static int[] ToIntArray(this string[] values)
{
int len = values.Length;
var indexIds = new int[len];
for (int i = 0; i < len; i++)
{
indexIds[i] = values[i].ToInt(0);
}
return indexIds;
}


58.EF 中必须 AsEnumerable() 之后才能group by

1).IQueryable 有诸多限制, 只支持数据库查询语法, 无法支持 Linq to object 的操作.

2).加了 AsEnumerable() 后运行正常, 因为 IEnumerable 支持 Linq to object 的操作.

简述Linq中.ToList(), .AsEnumerable(), AsQueryable()的区别和用法

LINQ语句中的.AsEnumerable() 和 .AsQueryable()的区别

/// <summary>
/// 分组查询
/// </summary>
/// <typeparam name="S"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="request"></param>
/// <param name="whereAndOrderBy"></param>
/// <returns></returns>
public virtual BaseResponse<IList<T>> GroupQuery<S, T>(BaseRequest request, Func<IEnumerable<S>, IEnumerable<S>> whereAndOrderBy) where S : class
{
BaseResponse<IList<T>> response = new BaseResponse<IList<T>>();
//Mapper.CreateMap<S, T>();
var q = from m in unitOfWork.GetRepository<S>().dbSet.AsEnumerable()
select m;

if (whereAndOrderBy != null)
{
q = whereAndOrderBy(q);
}
//创建一个参数c
ParameterExpression param =
Expression.Parameter(typeof(S), "c");
//c.IsDeleted=="false"
Expression left = Expression.Property(param,
typeof(S).GetProperty("IsDeleted"));
Expression right = Expression.Constant(false);
Expression filter = Expression.Equal(left, right);

Expression pred = Expression.Lambda(filter, param);
//Where(c=>c.IsDeleted==false)
//Expression expr = Expression.Call(typeof(Queryable), "Where",
//    new Type[] { typeof(S) },
//    Expression.Constant(q), pred);
//生成动态查询
//q = q.Provider.CreateQuery<S>(expr);
q = q.AsQueryable().Where((Expression<Func<S, bool>>)pred);

response.RecordsCount = q.Count();
List<S> list = null;
if (request != null && request.PageSize > 0)
{
list = q.Skip((request.CurrentPage - 1) * request.PageSize).Take(request.PageSize).ToList();
response.PagesCount = GetPagesCount(request.PageSize, response.RecordsCount);
}
else
{
list = q.ToList();
}

//response.Data = Mapper.Map<IList<T>>(list);
response.Data = Mapper.DynamicMap<IList<T>>(list);
return response;
}


59.EF 传实体,不能更新,需要先根据某个条件查询实体,然后再把传过来的值赋上,就可以更新实体。

60.实现一个条记录里面两个值要成对出现

思路:分别查出两个结果集,进行union(MySQL 里面用union),然后在根据主键ID分组,having count(Id)= 2,根据时间降序。

方法一 Linq 实现

var idlist = (from p in result
group p by p.ExaminationID into h
select new
{
key = h.Key,
count = h.Count(),
examDate = h.FirstOrDefault().ExaminationTime
} into c
where c.count == 2
orderby c.examDate descending
select c).Select(t => t.key).Take(7).ToList();


对应mysql 语句表示

SELECT * result
GROUP BY ExaminationID
HAVING COUNT(ExaminationID ) = 2
ORDER BY ExaminationTime DESC
LIMIT 7


方法二

var rest = (from height in resultHeight
join weight in resultWeight
on height.ExaminationID  equals weight.ExaminationID
select new
{
ExaminationTime = height.ExaminationTime,
CheckValueHeight = height.CheckValue,
CheckValueWeight = weight.CheckValue,
}).OrderByDescending(t => t.ExaminationTime).Take(7).ToList()


61.C# 正则 匹配字符中整个url

string str="网址为http://test.com/?key=123123 ,祝您生活愉快";
Regex re = new Regex("(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");
MatchCollection mc = re.Matches(str);
var url = "";
foreach (Match m in mc)
{
url = m.ToString();
}


62.监控网站,可以监控EF生成的sql dynatrace

63.asp.net webapi 集成swagger 自动生成webapi文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: