C#內(nèi)置泛型委托之Func委托
一、什么是Func委托
Func委托代表有返回類型的委托
二、Func委托定義
查看Func的定義:
using System.Runtime.CompilerServices;
namespace System
{
//
// 摘要:
// 封裝一個方法,該方法具有兩個參數(shù),并返回由 TResult 參數(shù)指定的類型的值。
//
// 參數(shù):
// arg1:
// 此委托封裝的方法的第一個參數(shù)。
//
// arg2:
// 此委托封裝的方法的第二個參數(shù)。
//
// 類型參數(shù):
// T1:
// 此委托封裝的方法的第一個參數(shù)的類型。
//
// T2:
// 此委托封裝的方法的第二個參數(shù)的類型。
//
// TResult:
// 此委托封裝的方法的返回值類型。
//
// 返回結(jié)果:
// 此委托封裝的方法的返回值。
[TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
}你會發(fā)現(xiàn),F(xiàn)unc其實就是有多個輸出參數(shù)并且有返回值的delegate。
3、示例
Func至少0個輸入?yún)?shù),至多16個輸入?yún)?shù),根據(jù)返回值泛型返回。必須有返回值,不可void。
Func<int> 表示沒有輸入?yún)?,返回值為int類型的委托。
Func<object,string,int> 表示傳入?yún)?shù)為object, string ,返回值為int類型的委托。
Func<object,string,int> 表示傳入?yún)?shù)為object, string, 返回值為int類型的委托。
Func<T1,T2,,T3,int> 表示傳入?yún)?shù)為T1,T2,,T3(泛型),返回值為int類型的委托。

代碼示例如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunDemo
{
class Program
{
static void Main(string[] args)
{
// 無參數(shù),只要返回值
Func<int> fun1 = new Func<int>(FunWithNoPara);
int result1= fun1();
Console.WriteLine(result1);
Console.WriteLine("----------------------------");
Func<int> fun2 = delegate { return 19; };
int result2 = fun2();
Console.WriteLine(result2);
Console.WriteLine("----------------------------");
Func<int> fun3 = () => { return 3; };
int result3 = fun3();
Console.WriteLine(result3);
Console.WriteLine("----------------------------");
//有一個參數(shù),一個返回值
Func<int, int> fun4 = new Func<int, int>(FunWithPara);
int result4 = fun4(4);
Console.WriteLine($"這里是一個參數(shù)一個返回值的方法,返回值是:{result4}");
Console.WriteLine("----------------------------");
// 使用委托
Func<int, string> fun5 = delegate (int i) { return i.ToString(); };
string result5 = fun5(5);
Console.WriteLine($"這里是一個參數(shù)一個返回值的委托,返回值是:{result5}");
Console.WriteLine("----------------------------");
// 使用匿名委托
Func<int, string> fun6 = (int i) =>
{
return i.ToString();
};
string result6 = fun6(6);
Console.WriteLine($"這里是一個參數(shù)一個返回值的匿名委托,返回值是:{result6}");
Console.WriteLine("----------------------------");
// 多個輸入?yún)?shù)
Func<int, string, bool> fun7 = new Func<int, string, bool>(FunWithMultiPara);
bool result7 = fun7(2, "2");
Console.WriteLine($"這里是有多個輸入?yún)?shù)的方法,返回值是:{result7}");
Console.WriteLine("----------------------------");
// 使用委托
Func<int, string, bool> fun8 = delegate (int i, string s)
{
return i.ToString().Equals(s) ? true : false;
};
bool result8 = fun8(2, "abc");
Console.WriteLine($"這里是有多個輸入?yún)?shù)的委托,返回值是:{result8}");
Console.WriteLine("----------------------------");
// 使用匿名委托
Func<int, string, bool> fun9 = (int i, string s) =>
{
return i.ToString().Equals(s) ? true : false;
};
bool result9 = fun9(45, "ert");
Console.WriteLine($"這里是有多個輸入?yún)?shù)的匿名委托,返回值是:{result9}");
Console.ReadKey();
}
static int FunWithNoPara()
{
return 10;
}
static int FunWithPara(int i)
{
return i;
}
static bool FunWithMultiPara(int i,string s)
{
return i.ToString().Equals(s) ? true : false;
}
}
}運行結(jié)果:

4、真實示例
在下面的示例中,利用Func委托封裝數(shù)據(jù)庫通用訪問類。
1、定義BaseModel基類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication.Model
{
public class BaseModel
{
public int Id { get; set; }
}
}2、定義Student類繼承自BaseModel基類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication.Model
{
public class Student : BaseModel
{
public string Name { get; set; }
public int Age { get; set; }
public int Sex { get; set; }
public string Email { get; set; }
}
}3、定義數(shù)據(jù)庫訪問方法接口
using FunApplication.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication.IDAL
{
public interface IBaseDAL
{
T Query<T>(int id) where T : BaseModel;
List<T> QueryAll<T>() where T : BaseModel;
int Insert<T>(T t) where T : BaseModel;
int Update<T>(T t) where T : BaseModel;
int Delete<T>(int id) where T : BaseModel;
}
}4、定義屬性幫助類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication.AttributeExtend
{
public static class AttributeHelper
{
public static string GetColumnName(this PropertyInfo prop)
{
if (prop.IsDefined(typeof(ColumnAttribute), true))
{
ColumnAttribute attribute = (ColumnAttribute)prop.GetCustomAttribute(typeof(ColumnAttribute), true);
return attribute.GetColumnName();
}
else
{
return prop.Name;
}
}
}
}5、定義ColumnAttribute類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication.AttributeExtend
{
[AttributeUsage(AttributeTargets.Property)]
public class ColumnAttribute : Attribute
{
public ColumnAttribute(string name)
{
this._Name = name;
}
private string _Name = null;
public string GetColumnName()
{
return this._Name;
}
}
}6、定義數(shù)據(jù)庫方法接口實現(xiàn)類
using FunApplication.IDAL;
using FunApplication.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using FunApplication.AttributeExtend;
namespace FunApplication.DAL
{
public class BaseDAL : IBaseDAL
{
// 數(shù)據(jù)庫鏈接字符串
private static string strConn = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;
public int Delete<T>(int id) where T : BaseModel
{
int result = 0;
using (SqlConnection conn = new SqlConnection(strConn))
{
string strSQL = "delete from Student where Id=@Id";
SqlParameter para = new SqlParameter("Id", id);
SqlCommand command = new SqlCommand(strSQL, conn);
command.Parameters.Add(para);
conn.Open();
result = command.ExecuteNonQuery();
}
return result;
}
public int Insert<T>(T t) where T : BaseModel
{
int result = 0;
using (SqlConnection conn = new SqlConnection(strConn))
{
Type type = typeof(T);
var propArray = type.GetProperties().Where(p => p.Name != "Id");
string strSQL = "insert into Student Values (@Name,@Age,@Sex,@Email) ";
SqlCommand command = new SqlCommand(strSQL, conn);
var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();
command.Parameters.AddRange(parameters);
conn.Open();
result = command.ExecuteNonQuery();
}
return result;
}
public T Query<T>(int id) where T : BaseModel
{
Type type = typeof(T);
string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));
string sql = $"SELECT {columnString} FROM [{type.Name}] WHERE Id={id}";
T t = null;// (T)Activator.CreateInstance(type);
using (SqlConnection conn = new SqlConnection(strConn))
{
SqlCommand command = new SqlCommand(sql, conn);
conn.Open();
SqlDataReader reader = command.ExecuteReader();
List<T> list = this.ReaderToList<T>(reader);
t = list.FirstOrDefault();
}
return t;
}
public List<T> QueryAll<T>() where T : BaseModel
{
Type type = typeof(T);
string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));
string sql = $"SELECT {columnString} FROM [{type.Name}] ";
List<T> list = new List<T>();
using (SqlConnection conn = new SqlConnection(strConn))
{
SqlCommand command = new SqlCommand(sql, conn);
conn.Open();
SqlDataReader reader = command.ExecuteReader();
list = this.ReaderToList<T>(reader);
}
return list;
}
public int Update<T>(T t) where T : BaseModel
{
int result = 0;
using (SqlConnection conn = new SqlConnection(strConn))
{
Type type = typeof(T);
var propArray = type.GetProperties().Where(p => p.Name != "Id");
string columnString = string.Join(",", propArray.Select(p => $"[{p.GetColumnName()}]=@{p.GetColumnName()}"));
var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();
//必須參數(shù)化 否則引號? 或者值里面還有引號
string strSQL = $"UPDATE [{type.Name}] SET {columnString} WHERE Id={t.Id}";
SqlCommand command = new SqlCommand(strSQL, conn);
command.Parameters.AddRange(parameters);
conn.Open();
result = command.ExecuteNonQuery();
}
return result;
}
private List<T> ReaderToList<T>(SqlDataReader reader) where T : BaseModel
{
Type type = typeof(T);
List<T> list = new List<T>();
while (reader.Read())//表示有數(shù)據(jù) 開始讀
{
T t = (T)Activator.CreateInstance(type);
foreach (var prop in type.GetProperties())
{
object oValue = reader[prop.GetColumnName()];
if (oValue is DBNull)
oValue = null;
prop.SetValue(t, oValue);//除了guid和枚舉
}
list.Add(t);
}
return list;
}
}
}7、在Main()方法中調(diào)用
using FunApplication.DAL;
using FunApplication.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication
{
class Program
{
static void Main(string[] args)
{
#region MyRegion
BaseDAL dal = new BaseDAL();
// 查詢
Student student = dal.Query<Student>(2);
Console.WriteLine($"姓名:{student.Name},年齡:{student.Age},Email地址:{student.Email}");
Console.WriteLine("----------------------------");
// 查詢所有
List<Student> list = dal.QueryAll<Student>();
Console.WriteLine($"集合個數(shù):{list.Count}");
Console.WriteLine("----------------------------");
// 插入
Student studentIns = new Student()
{
Name = "小明",
Age = 20,
Sex = 2,
Email = "xiaoming@qq.com"
};
bool resultIns = dal.Insert<Student>(studentIns) > 0 ? true : false;
Console.WriteLine($"插入執(zhí)行結(jié)果:{resultIns}");
Console.WriteLine("----------------------------");
// 更新
Student studentUpd = new Student()
{
Id = 1,
Name = "zhangsan1234",
Age = 20,
Sex = 2,
Email = "zhangsan1234@qq.com"
};
bool resultUpd = dal.Update<Student>(studentUpd) > 0 ? true : false;
Console.WriteLine($"更新執(zhí)行結(jié)果:{resultUpd}");
Console.WriteLine("----------------------------");
// 刪除
bool resultDel = dal.Delete<Student>(3) > 0 ? true : false;
Console.WriteLine($"刪除執(zhí)行結(jié)果:{resultDel}");
#endregion
Console.ReadKey();
}
}
}8、結(jié)果

9、優(yōu)化
仔細(xì)觀察上面步驟7中的代碼,你會發(fā)現(xiàn)在每個方法中都有重復(fù)的代碼,打開鏈接,執(zhí)行SqlCommand命令,那么這些重復(fù)的代碼能不能提取到一個公共的方法中進行調(diào)用呢?答案是可以的,那就是利用Func委托,看下面優(yōu)化后的代碼:
using FunApplication.AttributeExtend;
using FunApplication.IDAL;
using FunApplication.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication.DAL
{
public class FunBaseDAL : IBaseDAL
{
// 數(shù)據(jù)庫鏈接字符串
private static string strConn = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;
public int Delete<T>(int id) where T : BaseModel
{
Type type = typeof(T);
string sql = $"delete from {type.Name} where Id=@Id";
Func<SqlCommand, int> func = (SqlCommand command) =>
{
SqlParameter para = new SqlParameter("Id", id);
command.Parameters.Add(para);
return command.ExecuteNonQuery();
};
return ExcuteSql<int>(sql, func);
}
public int Insert<T>(T t) where T : BaseModel
{
int result = 0;
Type type = typeof(T);
var propArray = type.GetProperties().Where(p => p.Name != "Id");
string strSQL = "insert into Student Values (@Name,@Age,@Sex,@Email) ";
var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();
Func<SqlCommand, int> func = (SqlCommand command) =>
{
command.Parameters.AddRange(parameters);
return command.ExecuteNonQuery();
};
result = ExcuteSql<int>(strSQL, func);
return result;
}
public T Query<T>(int id) where T : BaseModel
{
Type type = typeof(T);
string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));
string sql = $"SELECT {columnString} FROM [{type.Name}] WHERE Id=@Id";
T t = null;
DataTable dt = new DataTable();
Func<SqlCommand, T> func = (SqlCommand command) =>
{
SqlParameter para = new SqlParameter("@Id", id);
command.Parameters.Add(para);
SqlDataAdapter adapter = new SqlDataAdapter(command);
//SqlDataReader reader = command.ExecuteReader();
//List<T> list = this.ReaderToList<T>(reader);
adapter.Fill(dt);
List<T> list = ConvertToList<T>(dt);
T tResult = list.FirstOrDefault();
return tResult;
};
t = ExcuteSql<T>(sql, func);
return t;
}
public List<T> QueryAll<T>() where T : BaseModel
{
Type type = typeof(T);
string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));
string sql = $"SELECT {columnString} FROM [{type.Name}] ";
T t = null;
Func<SqlCommand, List<T>> func = (SqlCommand command) =>
{
SqlDataReader reader = command.ExecuteReader();
List<T> list = this.ReaderToList<T>(reader);
return list;
};
return ExcuteSql<List<T>>(sql, func);
}
public int Update<T>(T t) where T : BaseModel
{
int result = 0;
Type type = typeof(T);
var propArray = type.GetProperties().Where(p => p.Name != "Id");
string columnString = string.Join(",", propArray.Select(p => $"[{p.GetColumnName()}]=@{p.GetColumnName()}"));
var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();
//必須參數(shù)化 否則引號? 或者值里面還有引號
string strSQL = $"UPDATE [{type.Name}] SET {columnString} WHERE Id={t.Id}";
Func<SqlCommand, int> func = (SqlCommand command) =>
{
command.Parameters.AddRange(parameters);
return command.ExecuteNonQuery();
};
result = ExcuteSql<int>(strSQL, func);
return result;
}
//多個方法里面重復(fù)對數(shù)據(jù)庫的訪問 想通過委托解耦,去掉重復(fù)代碼
private T ExcuteSql<T>(string sql, Func<SqlCommand, T> func)
{
using (SqlConnection conn = new SqlConnection(strConn))
{
using (SqlCommand command = new SqlCommand(sql, conn))
{
conn.Open();
SqlTransaction sqlTransaction = conn.BeginTransaction();
try
{
command.Transaction = sqlTransaction;
T tResult = func.Invoke(command);
sqlTransaction.Commit();
return tResult;
}
catch (Exception ex)
{
sqlTransaction.Rollback();
throw;
}
}
}
}
private List<T> ReaderToList<T>(SqlDataReader reader) where T : BaseModel
{
Type type = typeof(T);
List<T> list = new List<T>();
while (reader.Read())//表示有數(shù)據(jù) 開始讀
{
T t = (T)Activator.CreateInstance(type);
foreach (var prop in type.GetProperties())
{
object oValue = reader[prop.GetColumnName()];
if (oValue is DBNull)
oValue = null;
prop.SetValue(t, oValue);//除了guid和枚舉
}
list.Add(t);
}
reader.Close();
return list;
}
}
}10、在Main()方法中調(diào)用
using FunApplication.DAL;
using FunApplication.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunApplication
{
class Program
{
static void Main(string[] args)
{
#region 傳統(tǒng)實現(xiàn)
//BaseDAL dal = new BaseDAL();
//// 查詢
//Student student = dal.Query<Student>(2);
//Console.WriteLine($"姓名:{student.Name},年齡:{student.Age},Email地址:{student.Email}");
//Console.WriteLine("----------------------------");
//// 查詢所有
//List<Student> list = dal.QueryAll<Student>();
//Console.WriteLine($"集合個數(shù):{list.Count}");
//Console.WriteLine("----------------------------");
//// 插入
//Student studentIns = new Student()
//{
// Name = "小明",
// Age = 20,
// Sex = 2,
// Email = "xiaoming@qq.com"
//};
//bool resultIns = dal.Insert<Student>(studentIns) > 0 ? true : false;
//Console.WriteLine($"插入執(zhí)行結(jié)果:{resultIns}");
//Console.WriteLine("----------------------------");
//// 更新
//Student studentUpd = new Student()
//{
// Id = 1,
// Name = "zhangsan1234",
// Age = 20,
// Sex = 2,
// Email = "zhangsan1234@qq.com"
//};
//bool resultUpd = dal.Update<Student>(studentUpd) > 1 ? true : false;
//Console.WriteLine($"更新執(zhí)行結(jié)果:{resultUpd}");
//Console.WriteLine("----------------------------");
//// 刪除
//bool resultDel = dal.Delete<Student>(5) > 1 ? true : false;
//Console.WriteLine($"刪除執(zhí)行結(jié)果:{resultDel}");
#endregion
#region 利用委托
// 查詢
FunBaseDAL dal = new FunBaseDAL();
Student student = dal.Query<Student>(1);
Console.WriteLine($"姓名:{student.Name},年齡:{student.Age},Email地址:{student.Email}");
Console.WriteLine("----------------------------");
// 查詢所有
List<Student> list = dal.QueryAll<Student>();
Console.WriteLine($"集合個數(shù):{list.Count}");
Console.WriteLine("----------------------------");
// 插入
Student studentIns = new Student()
{
Name = "tom",
Age = 19,
Sex = 1,
Email = "tom@163.com"
};
bool resultIns = dal.Insert<Student>(studentIns) > 0 ? true : false;
Console.WriteLine($"插入執(zhí)行結(jié)果:{resultIns}");
Console.WriteLine("----------------------------");
List<Student> list1 = dal.QueryAll<Student>();
Console.WriteLine($"插入后集合個數(shù):{list1.Count}");
Console.WriteLine("----------------------------");
// 更新
Student studentUpd = new Student()
{
Id = 2,
Name = "馬六123",
Age = 20,
Sex = 2,
Email = "maliu1234@qq.com"
};
bool resultUpd = dal.Update<Student>(studentUpd) > 0 ? true : false;
Console.WriteLine($"更新執(zhí)行結(jié)果:{resultUpd}");
Console.WriteLine("----------------------------");
// 刪除
bool resultDel = dal.Delete<Student>(8) > 0 ? true : false;
Console.WriteLine($"刪除執(zhí)行結(jié)果:{resultDel}");
List<Student> list2 = dal.QueryAll<Student>();
Console.WriteLine($"刪除后集合個數(shù):{list2.Count}");
Console.WriteLine("----------------------------");
#endregion
Console.ReadKey();
}
}
}11、結(jié)果

注意
在使用SqlDataReader的時候有時會報錯:“已有打開的與此Command相關(guān)聯(lián)的DataReader,必須先將它關(guān)閉”。
同時打開兩個或循環(huán)多個sqldatareader會出現(xiàn)以上錯誤。因為用的是sqldatareader做數(shù)據(jù)庫的數(shù)據(jù)讀取,sqlconnection開啟沒有關(guān)閉。
一個SqlConnection只能執(zhí)行一次事務(wù),沒用一次必須關(guān)閉然后再開啟。上面我只用了一次沒有關(guān)閉,直接開啟所以會報錯。解決方案有如下兩種:
1、其實不用多次打開在開啟,那樣實現(xiàn)起來很麻煩。直接在連接字符串的后面加上MultipleActiveResultSets=true即可。 配置文件定義如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<!--<add name="DbConnection" connectionString="Server=.;Initial Catalog=MyDb;User ID=sa;Password=123456;MultipleActiveResultSets=True"/>-->
<!--配置文件里面添加MultipleActiveResultSets=True-->
<add name="DbConnection" connectionString="Server=.;Initial Catalog=MyDb;User ID=sa;Password=123456;MultipleActiveResultSets=True"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>2、使用DataTable
在上面是使用的SqlDataReader讀取數(shù)據(jù),然后轉(zhuǎn)換成List<T>,可以用DataTable代替SqlDataReader,這樣就不會報錯了,代碼如下:
/// <summary>
/// 將DataTable轉(zhuǎn)換成List
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dt"></param>
/// <returns></returns>
private List<T> ConvertToList<T>(DataTable dt) where T:BaseModel
{
Type type = typeof(T);
List<T> list = new List<T>();
foreach(DataRow dr in dt.Rows)
{
T t = (T)Activator.CreateInstance(type);
foreach(PropertyInfo prop in type.GetProperties())
{
object value = dr[prop.GetColumnName()];
if(value is DBNull)
{
value = null;
}
prop.SetValue(t, value);
}
list.Add(t);
}
return list;
}到此這篇關(guān)于C#內(nèi)置泛型委托之Func委托的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Unity實現(xiàn)卡片循環(huán)滾動效果的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用Unity實現(xiàn)卡片循環(huán)滾動的效果,文中的實現(xiàn)步驟講解詳細(xì),具有一定的借鑒價值,需要的可以參考一下2022-12-12
在C#中將Word轉(zhuǎn)換為PostScript的代碼實現(xiàn)
在需要高質(zhì)量打印或跨平臺文檔分發(fā)的場景中,將Word轉(zhuǎn)換為PostScript是專業(yè)選擇,所以本文給大家介紹了如何在 C# 中將 Word 轉(zhuǎn)換為 PostScript,需要的朋友可以參考下2025-09-09
C#使用時序數(shù)據(jù)庫InfluxDB的教程詳解
InfluxDB是一個開源的時序數(shù)據(jù)庫,可以自動處理時間序列數(shù)據(jù),這篇文章主要為大家詳細(xì)介紹了C#如何使用InfluxDB,感興趣的小伙伴可以跟隨小編一起了解下2023-11-11
關(guān)于C#中使用Oracle存儲過程返回結(jié)果集的問題
Oracle中可以使用游標(biāo)(Cursor)對數(shù)據(jù)集進行操作,但在存儲過程輸出參數(shù)中直接使用Cursor錯誤,下面小編給大家?guī)砹薈#中使用Oracle存儲過程返回結(jié)果集的問題,感興趣的朋友一起看看吧2021-10-10

