编辑2请阅读 :这是一个非常特定的问题,因为代码运行正常,它只是没有按照我希望的方式工作。在发布答案或评论之前,请仔细阅读并确保您了解我需要帮助的地方。非常感谢。
我是新手程序员/编码员。我正在尝试从所有员工假期的访问数据库表填充 DataTable ,其中包含所选员工假期的详细信息。目前,使用查询,我的代码计算数据库的[假日]表中有多少假期,这些假期具有所选员工的PayrollNo。从那里,它在程序中的 DataTable 中填充新行,其中第一个假期与相关的PayrollNo 按员工的假期数量。
例如:Ben有 3个假期,但该表格将在 3 行填充第一个假日。
这表明该计划正确计算了他的假期,但我在选择每个员工的假期方面做错了。
它还显示它以我想要的格式写入表格。
我希望能做的事情看起来很简单;让表格填满Ben的所有3个假期,而不仅仅是他的第一个假期。
以下是我的代码部分,其中迭代了所选员工在[Holiday]
中假期数量的循环。
DataTable dt = new DataTable(); //Creates Table
dt.Clear();
dt.Columns.Add("Hol/Abs", typeof(string)); // Column 0
dt.Columns.Add("FirstDay", typeof(DateTime)); // Column 1
dt.Columns.Add("LastDay", typeof(DateTime)); // Column 2
dt.Columns.Add("TotalDays", typeof(int)); // Column 3
dt.Columns.Add("Reason", typeof(string)); // Column 4
LblName.Text = PassName; //Loads Name
string ConnString = @"Provider = Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\HoliPlanData.accdb;Persist Security Info=False";
string Query = "SELECT PayrollNo FROM [Employee] WHERE (FirstName + ' ' + LastName) = @Name"; //Will supply selected Employee's PayrollNo
string CountHolQuery = "SELECT COUNT(*) FROM [Holiday] WHERE PayrollNo = @PayrollNo"; //Will count all of that Employee's Holidays
string CountAbsQuery = "SELECT COUNT(*) FROM [Absences] WHERE PayrollNo = @PayrollNo"; //Will count all of that Employee's Absences
string GetStartQuery = "SELECT StartDate FROM [Holiday] WHERE PayrollNo = @PayrollNo"; // Will select the start date of Holidays
string GetEndQuery = "SELECT EndDate FROM [Holiday] WHERE PayrollNo = @PayrollNo"; // Will select the start date of Absences
string GetReasonQuery = "SELECT Reason FROM [Holiday] WHERE PayrollNo = @PayrollNo";
string AbsGetStartQuery = "SELECT StartDate FROM [Absences] WHERE PayrollNo = @PayrollNo";
string AbsGetEndQuery = "SELECT EndDate FROM [Absences] WHERE PayrollNo = @PayrollNo";
string AbsGetReasonQuery = "SELECT Comments FROM [Absences] WHERE PayrollNo = @PayrollNo";
using (OleDbConnection conn = new OleDbConnection(ConnString))
using (OleDbCommand GetPayroll = new OleDbCommand(Query, conn))
{
conn.Open();
GetPayroll.Parameters.Add("@Name", OleDbType.VarChar).Value = LblName.Text;
int GotPayroll = Convert.ToInt32(GetPayroll.ExecuteScalar()); //Uses Query to Get PayrollNo
OleDbCommand CountRowsInHol = new OleDbCommand(CountHolQuery, conn);
OleDbCommand CountRowsInAbs = new OleDbCommand(CountAbsQuery, conn);
CountRowsInHol.Parameters.AddWithValue("@PayrollNo", OleDbType.Integer).Value = GotPayroll;
CountRowsInAbs.Parameters.AddWithValue("@PayrollNo", OleDbType.Integer).Value = GotPayroll;
int HolidayCount = (int) (CountRowsInHol.ExecuteScalar()); //Uses CountHolQuery to Get HowMany lines are in [Holiday]
int AbsenceCount = (int)(CountRowsInAbs.ExecuteScalar()); //Uses CountAbsQuery to Get HowMany lines are in [Absences]
int HolLoopCount = 1;
while (HolLoopCount <= HolidayCount) //Will go though all SelectedPayroll's holidays' in [Holiday]
{
OleDbCommand GetStart = new OleDbCommand(GetStartQuery, conn);
OleDbCommand GetEnd = new OleDbCommand(GetEndQuery, conn);
OleDbCommand GetReason = new OleDbCommand(GetReasonQuery, conn);
GetStart.Parameters.Add("@PayrollNo", OleDbType.Integer).Value = GotPayroll;
GetEnd.Parameters.Add("@PayrollNo", OleDbType.Integer).Value = GotPayroll;
GetReason.Parameters.Add("@PayrollNo", OleDbType.Integer).Value = GotPayroll;
DateTime StartHold = Convert.ToDateTime(GetStart.ExecuteScalar());
DateTime EndHold = Convert.ToDateTime(GetEnd.ExecuteScalar());
string ReasonHold = (GetReason.ExecuteScalar()).ToString();
DataRow NewLine = dt.NewRow();
NewLine["Hol/Abs"] = "Holiday";
NewLine["FirstDay"] = StartHold;
NewLine["LastDay"] = EndHold;
NewLine["TotalDays"] = GetNoWeekends(StartHold,EndHold);
NewLine["Reason"] = ReasonHold;
dt.Rows.Add(NewLine);
HolLoopCount = HolLoopCount + 1;
}
dataGridView1.DataSource = dt;
dataGridView1.Refresh();
}
我的假设是我必须通过[Holiday] Datatable本身迭代,或者在代码中创建另一个DataTable来存储所有相关行,然后从那里提取显示表的详细信息。 任何帮助或建议将不胜感激。
修改
我添加了剩余的代码来显示查询和进程。还要说明我如何填补表格,尽管概述了这不是问题发生的原因。
答案 0 :(得分:1)
要从MS Access数据库获取DataTable
,请使用以下示例代码段:
列表 1.使用DataTable
对象lib从MS Access获取OleDb
private DataTable GetDataTable(string strCN, string strSQL)
{
try
{
using (OleDbConnection _conn = new OleDbConnection(strCN))
{
using (OleDbCommand _command = new OleDbCommand())
{
_command.CommandType = CommandType.Text;
_command.Connection = _conn;
_command.CommandText = strSQL;
_conn.Open();
using (OleDbDataReader _dr = _command.ExecuteReader())
{
DataTable _dt = new DataTable();
_dt.Load(_dr);
return _dt;
}
}
}
}
catch
{
throw;
}
}
其中strCN
是连接字符串,strSQL
是您的SELECT查询。您可以调用此方法并将各种SQL查询作为参数传递。
与您的情况相关,它看起来不像正确的SQL SELECT查询来完成这项工作。如果您确实需要获取DataTable
然后将其绑定到数据感知控件(如GridView
),那么您应该使用上面提供的方法。如果只需要获得标量值,请使用清单2中的以下方法。
清单2. 使用OleDb
对象lib从MS Access获取标量值
/// <summary>
/// Read DB Read Scalar on SQL command input
/// </summary>
/// <param name="SQL">string</param>
/// <returns>string</returns>
private static string ReadScalar(string ConnString, string SQL)
{
string _ret;
try
{
using (OleDbConnection _conn = new OleDbConnection(ConnString))
{
using (OleDbCommand _command = new OleDbCommand(SQL, _conn))
{
_command.CommandType = CommandType.Text;
_conn.Open();
_ret = _command.ExecuteScalar().ToString();
}
return _ret;
}
}
catch { return null; }
}
希望这会有所帮助。
答案 1 :(得分:1)
首先对您的代码进行轻微(不完整)修订:
string ConnString = @"Provider = Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\HoliPlanData.accdb;Persist Security Info=False";
string Query = "SELECT PayrollNo FROM [Employee] WHERE (FirstName + ' ' + LastName) = @Name"; //Will supply selected Employee's PayrollNo
string getHolidayQuery = @"SELECT StartDate, EndDate, Reason
FROM [Holiday]
WHERE PayrollNo = @PayrollNo"; // Will select data from Holidays
string getAbsencesQuery = @"SELECT StartDate, EndDate, Comments
FROM [Absences]
WHERE PayrollNo = @PayrollNo";
var holidayData = new DataTable();
var absenceData = new DataTable();
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
var getPayroll = new OleDbCommand(Query, conn);
getPayroll.Parameters.AddWithValue("@name", LblName.Text);
var holidaysQuery = new OleDbCommand(getHolidayQuery, conn);
var absencesQuery = new OleDbCommand(getAbsencesQuery, conn);
conn.Open();
int GotPayroll = Convert.ToInt32(getPayroll.ExecuteScalar()); //Uses Query to Get PayrollNo
holidaysQuery.Parameters.AddWithValue("@PayrollNo", GotPayroll);
absencesQuery.Parameters.AddWithValue("@PayrollNo", GotPayroll);
holidayData.Load(holidaysQuery.ExecuteReader());
absenceData.Load(absencesQuery.ExecuteReader());
conn.Close();
}
foreach (DataRow row in holidayData.AsEnumerable())
{
// here you could craft a new data table
// however there is a discrepancy.
// How would the data in Holiday would relate to those
// in absences. With the relation known, we might have
// gotten a single datatable from the database.
// Probably you should give data samples.
// DateTime StartHold = Convert.ToDateTime(GetStart.ExecuteScalar());
// DateTime EndHold = Convert.ToDateTime(GetEnd.ExecuteScalar());
// string ReasonHold = (GetReason.ExecuteScalar()).ToString();
// Above lines are sort of saying:
// DateTime StartHold = (DateTime)row["StartDate"];
// DateTime EndHold = (DateTime)row["EndDate"];
// string ReasonHold = (string)row["Reason"];
// without roundtripping to database per field
}
//...
基本上,我的意思是,不是每个字段执行一个标量,而是对数据库进行一次调用。使用标量方法,查询中没有任何内容可以区分&#34;首先&#34;从第二个或第三个排。 ie:对于payrollNo 5,假设有3个假期条目:
5, Jan 22, 2016, Jan 26, 2016
5, Feb 1, 2016, Feb 5, 2016
5, Feb 22, 2016, Feb 26, 2016
使用您的查询,只使用PayrollNo作为标准,您将始终从第一行(2016年1月22日,例如startDate)获取值。
首先将此数据放入本地数据表中,至少提供可迭代的结构。
从这个数据或直接从源数据创建一个数据表,使用Linq就像我最初说的一样容易(Linq它是IQueryable而不是DataTable,但也可以用DataTable)。 Linq是C#本身的一部分:)意味着语言集成查询 - IOW查询语言内置于C#本身。这是一个Linq代码,用于查询示例Northwind中的一些数据(使用来自codeplex的IQToolkit) - 这是您需要的所有代码,包括Form和DataGridView:
void Main()
{
string path = @"D:\data\Northwind.accdb";
string conStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="+path;
var provider= new AccessQueryProvider(new OleDbConnection(conStr),
new ImplicitMapping(), QueryPolicy.Default);
var sampleOrders = provider.GetTable<Order>("Orders")
.Where (o => o.OrderDate == new DateTime(1997,1,1));
Form f = new Form{Height=800,Width=1024};
DataGridView dgv = new DataGridView { Dock=DockStyle.Fill };
dgv.DataSource = sampleOrders.ToList();
f.Controls.Add(dgv);
f.Show();
}
// Entity Class
public class Order {
public int OrderID { get; set; }
public string CustomerID { get; set; }
public int EmployeeID { get; set; }
public DateTime OrderDate { get; set; }
public DateTime? RequiredDate { get; set; }
public DateTime? ShippedDate { get; set; }
public int ShipVia { get; set; }
public decimal? Freight { get; set; }
public string ShipCity { get; set; }
public string ShipCountry { get; set; }
}