[英]How can I retrieve data from a foreign key table in SQL with C#
我正在嘗試構建我的第一個用於學習目的的應用程序,但我遇到了困難。我的目標是從一個標有 PC 的表和幾個具有 ID 和字符串值的外鍵表中檢索數據。 我能夠執行 SQL 查詢,從 PC 表中檢索所有信息(不包括外鍵 ID),但我希望能夠看到電腦的“品牌”和“型號”。
我的錯誤信息
System.InvalidCastException: 'Specified cast is not valid.'
我的電腦 model 在 C# 看起來像這樣
public class PC
{
public int PC_ID { get; set; }
public string PC_SERIAL { get; set; }
public string PC_NAME { get; set; }
public Nullable<int> PC_BRAND_ID { get; set; }
public PCBrand PC_Brand { get; set; }
public Nullable<int> PC_MODEL_ID { get; set; }
public PCBrand PC_Model { get; set; }
public Nullable<int> PC_OS_ID { get; set; }
public PCOS PC_OS { get; set; }
public Nullable<int> PC_NET_ID { get; set; }
public PCNet PC_Net { get; set; }
public Nullable<int> PC_RAM_ID { get; set; }
public PCRam PC_Ram { get; set; }
public override string ToString()
{
return $"{PC_ID} - {PC_NAME} - {PC_SERIAL} - {PC_Model} - {PC_Brand} - {PC_OS} - {PC_Net} - {PC_Ram}";
}
}
例如,我的一個外鍵表如下所示:
namespace Inventory.Data.Model
{
public class PCBrand
{
public int PC_BRAND_ID { get; set; }
public string PC_BRAND { get; set; }
}
}
這是我存儲庫中的代碼 class
private const string SqlGetAllPC = @"Select PC.PC_ID, PC.PC_NAME,
PC_BRAND.PC_BRAND,PC_MODEL.PC_MODEL,PC_NET.
PC_NET,PC_OS.PC_OS,PC_RAM.PC_RAM
FROM PC
INNER JOIN PC_BRAND on PC.PC_BRAND_ID=PC_BRAND.PC_BRAND_ID
INNER JOIN PC_MODEL ON PC.PC_MODEL_ID=PC_MODEL.PC_MODEL_ID
INNER JOIN PC_NET ON PC.PC_NET_ID=PC_NET.PC_NET_ID
INNER JOIN PC_OS ON PC.PC_OS_ID=PC_OS.PC_OS_ID
INNER JOIN PC_RAM ON PC.PC_RAM_ID=PC_RAM.PC_RAM_ID";
public IEnumerable<PC> GetAllFromPc()
{
IEnumerable<PC> list = null;
try
{
connector.OpenConnection();
System.Data.DataTable data = connector.GetData(SqlGetAllPC);
if (data != null && data.Rows.Count > 0)
{
list = ConvertToPC(data);
}
}
catch (Exception)
{
throw;
}
finally
{
connector.CloseConnection();
}
return list;
}
private IEnumerable<PC> ConvertToPC(DataTable data)
{
List<PC> tmp = new List<PC>();
foreach (DataRow row in data.Rows)
{
tmp.Add(new PC()
{
PC_ID = row.Field<int>(0),
PC_SERIAL = row.Field<string>(1),
PC_NAME = row.Field<string>(2),
PC_BRAND_ID = row.Field<int>(3),
PC_MODEL_ID = row.Field<int>(4),
PC_OS_ID = row.Field<int>(5),
PC_NET_ID = row.Field<int>(6),
PC_RAM_ID = row.Field<int>(7),
});
}
return tmp;
}
}
最后是我檢索數據的按鈕
private void GetAllButton(object sender, RoutedEventArgs e)
{
Data.Repositories.PCRepository newpc = new Data.Repositories.PCRepository();
IEnumberable<Data.Model.PC> data = newpc.GetAllFromPc();
if (data != null)
{
StringBuilder sb = new StringBuilder();
data.ToList()
.ForEach(x=> sb.AppendLine(x.ToString()))
MessageBox.Show(sb.ToString());
}
}
通過一些編輯,我能夠從我的 PC 標簽中檢索。 但我還想從數據庫中的 PC_Brand 和 PC_Model 表中檢索 PC 的型號/品牌名稱。
您的SELECT
正在讀取我認為是字符串值的內容(PC_MODEL.PC_MODEL、PC.NET.PC.NET、PC_OS.PC_OS、PC_RAM.PC_RAM),但您將它們分配給整數,因此轉換無效。
為什么我確定這些是字符串? 因為你的加入。 您正在加入,例如 PC_MODEL_ID,它幾乎肯定是整數。
將您的SELECT
更改為:
SELECT PC.PC_ID, PC.PC_NAME, PC_BRAND.PC_BRAND,PC.PC_MODEL_ID, PC.PC_NET_ID, PC.PC_OS_ID,PC.PC_RAM_ID
FROM PC
INNER JOIN PC_BRAND on PC.PC_BRAND_ID=PC_BRAND.PC_BRAND_ID
INNER JOIN PC_MODEL ON PC.PC_MODEL_ID=PC_MODEL.PC_MODEL_ID
請注意,如果您只選擇 integer 值,則不需要所有其他聯接。
編輯
您需要將 select 更改為
SELECT PC.PC_ID, PC.PC_SERIAL, PC.PC_NAME,
PC_BRAND.PC_BRAND, PC.PC_BRAND_ID,
PC_MODEL.PC_MODEL, PC.PC_MODEL_ID,
PC_NET.PC_NET, PC.PC_NET_ID,
PC_OS.PC_OS, PC.PC_OS_ID,
PC_RAM.PC_RAM, PC.PC_RAM_ID
FROM PC
INNER JOIN PC_BRAND on PC.PC_BRAND_ID = PC_BRAND.PC_BRAND_ID
INNER JOIN PC_MODEL ON PC.PC_MODEL_ID = PC_MODEL.PC_MODEL_ID
INNER JOIN PC_NET ON PC.PC_NET_ID = PC_NET.PC_NET_ID
INNER JOIN PC_OS ON PC.PC_OS_ID = PC_OS.PC_OS_ID
INNER JOIN PC_RAM ON PC.PC_RAM_ID= PC_RAM.PC_RAM_ID
現在您可以在 ConvertToPC 中執行類似的操作:
private static IEnumerable<PC> ConvertToPC(DataTable data)
{
List<PC> tmp = new List<PC>();
foreach (DataRow row in data.Rows)
{
tmp.Add(new PC()
{
PC_ID = row.Field<int>(0),
PC_SERIAL = row.Field<string>(1),
PC_NAME = row.Field<string>(2),
PC_Brand = new PCBrand
{
PC_BRAND = row.Field<string>(3),
PC_BRAND_ID = row.Field<int>(4)
},
PC_BRAND_ID = row.Field<int>(4),
PC_Model = new PCModel
{
PC_MODEL = row.Field<string>(5),
PC_MODEL_ID = row.Field<int>(6)
},
PC_MODEL_ID = row.Field<int>(6),
PC_Net = new PCNet
{
PC_NET = row.Field<string>(7),
PC_NET_ID = row.Field<int>(8)
},
PC_NET_ID = row.Field<int>(8),
PC_OS = new PCOS
{
PC_OS = row.Field<string>(9),
PC_OS_ID = row.Field<int>(10)
},
PC_OS_ID = row.Field<int>(10),
PC_Ram = new PCRam
{
PC_RAM = row.Field<string>(11),
PC_RAM_ID = row.Field<int>(12)
},
PC_RAM_ID = row.Field<int>(12)
});
}
return tmp;
}
請注意,我已盡可能少地更改您的代碼。 在實踐中,我會做很多不同的事情。 例如,現在所有外鍵 ID 都是重復的:您的 PC class 中不再同時具有 PCModel 類型的 object 和 int PC_MODEL_ID,您只需要 object PCModel,因為它已經包含 ID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.