如果我有一个结构如下的表怎么办?
X - Y
3 / 10
5 / 7
2 / 15
所以这些是某种坐标。我如何通过 LINQ to SQL 将它们写入 SQL 服务器表?
换句话说,如何将图形的坐标点保存到单个表中?
如果我有一个结构如下的表怎么办?
X - Y
3 / 10
5 / 7
2 / 15
所以这些是某种坐标。我如何通过 LINQ to SQL 将它们写入 SQL 服务器表?
换句话说,如何将图形的坐标点保存到单个表中?
是的。正常的数据库表是“二维”的,一个维度上有一组名称和类型的列,另一个维度有零个或多个行。
请注意,这与在二维空间中表示空间中的点的“X”和“Y”无关。如果你有“X”、“Y”和“Z”,代表 3 维空间中的点,那么数据仍然是 2 维的。
因此,它与任何其他数据库表相同,因此只需使用 Linq2Sql、EntityFramework、Linq2NHibernate 或任何其他您想要的 linq 数据库查询源,并以它拥有的方式写入表。例如,使用 Linq2SQL,您可以更改从表中获取的实体上的字段或使用 or 添加新记录InsertOnSubmit()
,InsertAllOnSubmit()
然后调用数据SubmitChanges()
上下文。
让我们以 Linq2SQL 为例,尽管其他方法也是如此。
让我们首先在 SQL 中创建一个表(或者,您也可以反过来,我个人更喜欢手动分别创建每个表,但是有一些工具可以从 SQL 和 C# 创建 SQL)。
CREATE TABLE Coordinates
(
id int identity primary key not null,
x int not null,
y int not null
)
我们并不严格需要该id
列,但它会在很多方面让我们的生活更轻松,特别是如果我们想要拥有多个相同 x 和 y 的实例 - 必须有某种 id使更新成为可能。
现在,下一点看起来会比实际情况更复杂。实际上,如果这是从检查 DB 生成的 DBML 生成的,那么它将partial
用于将大部分实现放在您不需要查看的文件中。否则,如果您是手工完成的,您可以使用从一个公共类继承来在大部分重复上使用重用。
[Table(Name="dbo.Coordinates")]
public class Coordinate : INotifyPropertyChanging, INotifyPropertyChanged
{
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
private int _id;
private int _x;
private int _y;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
protected void OnPropertyChanging(string name)
{
PropertyChangingEventHandler handler = PropertyChanging;
if (handler != null)
handler(this, new PropertyChangingEventArgs(name));
}
[Column(Storage = "_id", AutoSync = AutoSync.OnInsert, DbType = "Int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
public int Id
{
get
{
return _id;
}
set
{
if(_id != value)
{
SendPropertyChanging("Id");
_id = value;
SendPropertyChanged("Id");
}
}
}
[Column(Storage = "_x", DbType = "Int NOT NULL")]
public int X
{
get
{
return _x;
}
set
{
if(_x != value)
{
SendPropertyChanging("X");
_x = value;
SendPropertyChanged("X");
}
}
}
[Column(Storage = "_y", DbType = "Int NOT NULL")]
public int Y
{
get
{
return _y;
}
set
{
if(_y != value)
{
SendPropertyChanging("Y");
_y = value;
SendPropertyChanged("Y");
}
}
}
}
如前所述,这让事情看起来比你实际要处理的更糟。您通常可以将课程视为:
public class Coordinate
{
public int Id { get; set; }
public int X { get; set; }
public int Y { get; set; }
}
尽管如此,尽管您只需要担心这一点,但一些支持其他方法的人将样板代码的数量作为他们的论据之一。
无论如何,您还有一个数据上下文类可以处理所有这些。如果调用db.GetTable<Coordinate>()
它,则返回一个表示数据库中表的对象。因为您会经常这样做,所以通常会在派生的类上创建一个属性DataContext
,让我们为您执行此操作:
public Table<Coordinate> Coordinates
{
get { return GetTable<Coordinate>(); }
}
(再次,使用 DBML 并为您完成此操作)。
现在,让我们从添加三个坐标的示例列表开始:
using(var db = new OurDataContext(connString))
{
var tab = db.Coordinates;
tab.InsertOnSubmit(new Coordinates{X=3,Y=10});
tab.InsertOnSubmit(new Coordinates{X=5,Y=7});
tab.InsertOnSubmit(new Coordinates{X=2,Y=15});
db.SubmitChanges();
}
(变成一堆 SQL 插入)
到目前为止,很无聊。让我们添加 500 个新条目:
private static IEnumerable<Coordinate> ProduceRandomCoordinates(int num)
{
var rnd = new Random();
while(num-- > 0)
yield return new Coordinate{X=rnd.Next(-100, 101), Y=rnd.Next(-100, 101)};
}
using(var db = new OurDataContext(connString))
{
var tab = db.Coordinates;
tab.InsertAllOnSubmit(ProduceRandomCoordinates(500));
db.SubmitChanges();
}
(变成一堆 SQL 插入)
让我们看看我们有多少:
using(var db = new OurDataContext(connString))
Console.WriteLine(db.Coordinates.Count());
(变成 SQL SELECT COUNT(*) from Coordinates
);
让我们看看有多少 X 大于 Y:
using(var db = new OurDataContext(connString))
Console.WriteLine(db.Coordinates.Count(co => co.X > co.Y)
(变成 SQL SELECT COUNT(*) FROM Coordinates where x > y
)
让我们删除所有对 X 和 Y 都不是正数的
using(var db = new OurDataContext(connString))
{
var tab = db.Coordinates;
tab.DeleteAllOnSubmit(tab.Where(co => co.X < 0 || co.Y < 0));
db.SubmitChanges();
}
等等等等。真正有用的查询是我们连接多个表并根据标准选择子集,然后将它们调整为包含我们关心的关于整个数据库状态的信息的匿名对象。