[英]How can I retrieve data from a foreign key table in SQL with C#
I'm trying to build my first application for learning purposes but I've hit a wall.. My goal is to retrieve data from a table labeled PC and several foreign key tables that has an ID and a string value.我正在尝试构建我的第一个用于学习目的的应用程序,但我遇到了困难。我的目标是从一个标有 PC 的表和几个具有 ID 和字符串值的外键表中检索数据。 I was able to do a SQL query that retrieved all the information from the PC table (uncluding foreign key ID's) but I want to be able to see the "brand" and "model" of a pc.
我能够执行 SQL 查询,从 PC 表中检索所有信息(不包括外键 ID),但我希望能够看到电脑的“品牌”和“型号”。
My errormessage我的错误信息
System.InvalidCastException: 'Specified cast is not valid.'
My PC model in C# looks like this我的电脑 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}";
}
}
For instance, one of my foreign key tables looks like this:例如,我的一个外键表如下所示:
namespace Inventory.Data.Model
{
public class PCBrand
{
public int PC_BRAND_ID { get; set; }
public string PC_BRAND { get; set; }
}
}
And this is my code in my repository class这是我存储库中的代码 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;
}
}
And at last my button that retrieves the data最后是我检索数据的按钮
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());
}
}
With some editing I was able to retrieve from my PC tabel.通过一些编辑,我能够从我的 PC 标签中检索。 But I also want to retrieve the PC's model/brand name from the PC_Brand and PC_Model table in my database.
但我还想从数据库中的 PC_Brand 和 PC_Model 表中检索 PC 的型号/品牌名称。
Your SELECT
is reading what I take to be string values (PC_MODEL.PC_MODEL, PC.NET.PC.NET, PC_OS.PC_OS, PC_RAM.PC_RAM), but you are assigning them to integers, hence the invalid cast.您的
SELECT
正在读取我认为是字符串值的内容(PC_MODEL.PC_MODEL、PC.NET.PC.NET、PC_OS.PC_OS、PC_RAM.PC_RAM),但您将它们分配给整数,因此转换无效。
Why am I sure that these are strings?为什么我确定这些是字符串? Because of your joins.
因为你的加入。 You are joining on eg PC_MODEL_ID which are almost certainly integers.
您正在加入,例如 PC_MODEL_ID,它几乎肯定是整数。
Change your SELECT
to:将您的
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
Note that you do not need all the other joins, if you are only selecting the integer values.请注意,如果您只选择 integer 值,则不需要所有其他联接。
EDIT编辑
The you need to change your select to您需要将 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
Now you can do something like this in ConvertToPC:现在您可以在 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;
}
Please note that I have changed your code by as little as possible.请注意,我已尽可能少地更改您的代码。 In practice I would do a lot of things very differently.
在实践中,我会做很多不同的事情。 For example, all the foreign key ids are now duplicated: instead of having both an object of type PCModel and an int PC_MODEL_ID in your PC class, you only need the object PCModel, because it already contains the ID.
例如,现在所有外键 ID 都是重复的:您的 PC class 中不再同时具有 PCModel 类型的 object 和 int PC_MODEL_ID,您只需要 object PCModel,因为它已经包含 ID。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.