C# - Entity Framework 代码优先 - 将对象映射到两个表中
C# - Entity Framework code-first - map object into two tables
假设我有这样定义的数据模型:
class Geometry
{
public ICollection<Point> Points { get; set; }
}
class Point
{
public int X { get; set; }
public int Y { get; set; }
}
我想将其映射到以下数据库表中:
GeometriesTable
-- [GeometryId] int, key
-- [GeometryData] <-- a BLOB here!!!
PointsTable
-- [PointId] int, key
-- [GeometryId] int, foreign key
-- [X] int
-- [Y] int
我的 [GeometryData]
BLOB 基本上由构成几何图形的点 ID 和一些额外的元信息组成。
除去元数据,那些 BLOB 将如下所示:
[ N (points count) - 4 bytes ]
[ Points[0].Id - 4 bytes ]
[ Points[1].Id - 4 bytes ]
[ Points[2].Id - 4 bytes ]
...
[ Points[N-1].Id - 4 bytes ]
(即每个 BLOB (N+1)*4 个字节。)
出于几个性能原因,使用 BLOB(而不是简单的一对多关系)。那是无法改变的。
我创建了以下实体来投影模型:
class GeometryEntity
{
[Key]
[Column("GeometryId")]
public int Id { get; set; }
[Column("GeometryData")]
public byte[] Data { get; set; }
}
class PointEntity
{
[Key]
[Column("PointId")]
public int Id { get; set; }
[Column("GeometryId")]
public int GeometryId { get; set; }
[Column("X")]
public int X { get; set; }
[Column("Y")]
public int Y { get; set; }
}
现在,如果我有一些 IEnumerable<Geometry>
,我希望能够填充表格(一个 DbSet<GeometryEntity>
和一个 DbSet<PointEntity>
)。特殊问题是我不知道如何将 PointsTable
中的点 ID 分配给几何 BLOB 中的相应点 ID。
知道如何解决这样的映射吗?
Now, provided I have some IEnumerable<Geometry>
I would like to be
able to populate the tables (a DbSet<GeometryEntity>
and a
DbSet<PointEntity>
).
好的,让我们定义
IEnumerable<Geometry> ProvidedGeometries =
new Geometry[]
{
new Geometry()
{
Points = new PointEntity[]
{
new PointEntity() { GeometryId=1, X=1, Y=1, Id = 1},
new PointEntity() { GeometryId=1, X=1, Y=2, Id = 2},
new PointEntity() { GeometryId=1, X=2, Y=1, Id = 3},
new PointEntity() { GeometryId=1, X=2, Y=2, Id = 4}
}
},
new Geometry()
{
Points = new PointEntity[]
{
new PointEntity() { GeometryId=2, X=1, Y=1, Id = 5},
new PointEntity() { GeometryId=2, X=1, Y=2, Id = 6}
}
}
};
我认为您可以使用 Configuration.Seed
.
填充表格
用下面的伪代码
protected override void Seed(YourContext context)
{
context.GeometryEntities.AddOrUpdate(
// see the following Linq part
);
context.PointEntities.AddOrUpdate(
// see the following Linq part
);
}
或通过 SaveChanges
的标准更新
using (var ctx = new YourContext())
{
ctx.PointEntities.AddRange(Points); //see below
ctx.GeometryEntites.AddRange(Geometries); // " "
ctx.SaveChanges();
}
The particular problem is that I don't know how to assign points IDs
from the PointsTable
to the corresponding points IDs in my geometry
BLOBs.
除了 context
的 specific EF implementation 之外,我认为以下代码可以让您了解Linq 部分。
IEnumerable<PointEntity> Points =ProvidedGeometries
.SelectMany(g => g.Points);
var geometries = Points.GroupBy(
p => p.GeometryId,
p => BitConverter.GetBytes(p.Id),
(id, points) =>
new GeometryEntity()
{
Id = id,
Data =
BitConverter.GetBytes(points.Count()).Concat(
points.Aggregate( (a,b) => a.Concat(b).ToArray() )
).ToArray()
}
);
假设我有这样定义的数据模型:
class Geometry
{
public ICollection<Point> Points { get; set; }
}
class Point
{
public int X { get; set; }
public int Y { get; set; }
}
我想将其映射到以下数据库表中:
GeometriesTable
-- [GeometryId] int, key
-- [GeometryData] <-- a BLOB here!!!
PointsTable
-- [PointId] int, key
-- [GeometryId] int, foreign key
-- [X] int
-- [Y] int
我的 [GeometryData]
BLOB 基本上由构成几何图形的点 ID 和一些额外的元信息组成。
除去元数据,那些 BLOB 将如下所示:
[ N (points count) - 4 bytes ]
[ Points[0].Id - 4 bytes ]
[ Points[1].Id - 4 bytes ]
[ Points[2].Id - 4 bytes ]
...
[ Points[N-1].Id - 4 bytes ]
(即每个 BLOB (N+1)*4 个字节。)
出于几个性能原因,使用 BLOB(而不是简单的一对多关系)。那是无法改变的。
我创建了以下实体来投影模型:
class GeometryEntity
{
[Key]
[Column("GeometryId")]
public int Id { get; set; }
[Column("GeometryData")]
public byte[] Data { get; set; }
}
class PointEntity
{
[Key]
[Column("PointId")]
public int Id { get; set; }
[Column("GeometryId")]
public int GeometryId { get; set; }
[Column("X")]
public int X { get; set; }
[Column("Y")]
public int Y { get; set; }
}
现在,如果我有一些 IEnumerable<Geometry>
,我希望能够填充表格(一个 DbSet<GeometryEntity>
和一个 DbSet<PointEntity>
)。特殊问题是我不知道如何将 PointsTable
中的点 ID 分配给几何 BLOB 中的相应点 ID。
知道如何解决这样的映射吗?
Now, provided I have some
IEnumerable<Geometry>
I would like to be able to populate the tables (aDbSet<GeometryEntity>
and aDbSet<PointEntity>
).
好的,让我们定义
IEnumerable<Geometry> ProvidedGeometries =
new Geometry[]
{
new Geometry()
{
Points = new PointEntity[]
{
new PointEntity() { GeometryId=1, X=1, Y=1, Id = 1},
new PointEntity() { GeometryId=1, X=1, Y=2, Id = 2},
new PointEntity() { GeometryId=1, X=2, Y=1, Id = 3},
new PointEntity() { GeometryId=1, X=2, Y=2, Id = 4}
}
},
new Geometry()
{
Points = new PointEntity[]
{
new PointEntity() { GeometryId=2, X=1, Y=1, Id = 5},
new PointEntity() { GeometryId=2, X=1, Y=2, Id = 6}
}
}
};
我认为您可以使用 Configuration.Seed
.
用下面的伪代码
protected override void Seed(YourContext context)
{
context.GeometryEntities.AddOrUpdate(
// see the following Linq part
);
context.PointEntities.AddOrUpdate(
// see the following Linq part
);
}
或通过 SaveChanges
using (var ctx = new YourContext())
{
ctx.PointEntities.AddRange(Points); //see below
ctx.GeometryEntites.AddRange(Geometries); // " "
ctx.SaveChanges();
}
The particular problem is that I don't know how to assign points IDs from the
PointsTable
to the corresponding points IDs in my geometry BLOBs.
除了 context
的 specific EF implementation 之外,我认为以下代码可以让您了解Linq 部分。
IEnumerable<PointEntity> Points =ProvidedGeometries
.SelectMany(g => g.Points);
var geometries = Points.GroupBy(
p => p.GeometryId,
p => BitConverter.GetBytes(p.Id),
(id, points) =>
new GeometryEntity()
{
Id = id,
Data =
BitConverter.GetBytes(points.Count()).Concat(
points.Aggregate( (a,b) => a.Concat(b).ToArray() )
).ToArray()
}
);