C# 实体框架关系
我有以下三个实体:C# 实体框架关系,c#,entity-framework,C#,Entity Framework,我有以下三个实体: public class Dog { public int DogId { get; set; } public string Name { get; set; } public int Age { get; set; } public bool Checked { get; set; } public string DogImage { get; set; } public virtual ICollection<Re
public class Dog
{
public int DogId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Checked { get; set; }
public string DogImage { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public class Event
{
public int EventId { get; set; }
public string EventName { get; set; }
public string EventLocation { get; set; }
public string EventType { get; set; }
public string EventDate { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public class Result
{
public int ResultId { get; set; }
public int Track { get; set; }
public int Obedience { get; set; }
public int Protection { get; set; }
[ForeignKey("Dog")]
public int DogId { get; set; }
public virtual Dog Dog { get; set; }
[ForeignKey("Event")]
public int EventId { get; set; }
public virtual Event Event { get; set; }
}
现在我想下一步应该是在这个事件中添加一个狗的列表,为了做到这一点,我需要以某种方式使用我的result类,因为这是“glue”类。请让我知道我是否在正确的轨道上。我只使用fluent方法完成了这项工作(当我学习时,我发现你可以用fluent做任何事情,但不能用注释,所以我没有研究注释),以下内容在我的
单位
实体和我的单位服务
实体之间创建了多对多:
modelBuilder.Entity<Unit>()
.HasMany<UnitService>(u => u.Services)
.WithMany(us => us.Units);
像你这样建立多对多的关系并不是一个好主意 为了获得一个适当的多对多关系,在数据库中以适当的方式映射,并且没有陷阱,我将尝试以下方法:
public class Dog {}
public class Event {}
public class Result {}
// This is a linking table between Dog and Results
public class DogResult
{
public int Id {get;set;}
public int DogId {get;set;}
public int ResultId {get;set;}
}
// This is a linking table between Events and Results
public class EventResult
{
public int Id {get;set;}
public int EventId {get;set;}
public int ResultId {get;set;}
}
现在编写查询时,可以执行以下操作:
using (var context = new DbContext())
{
var dogs = context.Dogs();
var dogResults = context.DogResults();
var results = context.Results();
var dogsAndResults = dogs.Join(
dogResults,
d => d.Id,
r => r.DogId,
(dog, dogResult) => new { dog, dogResult })
.Join(
results,
a => a.dogResult.ResultId,
r => r.Id,
(anon, result) => new { anon.dog, result });
}
它看起来有点难看,但它会返回一个匿名对象列表,其中包含狗及其相关的结果。但显然,最好在存储过程中执行此操作:
using (var context = new DbContext())
{
var results = context.Database.ExecuteStoreQuery<SomeResultDto>("SELECT * .... JOIN ... ");
}
如何创建这些链接完全取决于您。要将其转换为存储过程,您需要创建一些自定义的用户定义表类型,并将其用作表值参数
var dogResults = dogs.SelectMany( d => results.Select ( r => new DogResult { DogId = d.Id, ResultId = r.Id } ) );
这是一个LINQ查询的野兽,基本上它获取每只狗并将其链接到每一个结果。在LinqPad中运行它并Dump
值。非常感谢,我将尝试研究一下,看看我是否能理解它。谢谢但是你的意思是我应该让我的类保持原样,仅仅添加两个新类?Dogresult和Eventresult?或者我必须在我的其他三个类中进行其他更改?只需添加两个额外的类,其他类保持不变!除此之外,您还需要删除导航属性。好的!导航属性中是否包含虚拟一词?2个ICollection和2个“常规属性”?是的。这些属性必须指示EF在您请求之前不要获取其值。这可能导致选择N+1情况。哪个不理想。事件包含ICollection不是更好吗?然后,Dog将包含其结果,以便您能够按事件顺序对这些狗进行排序。狗也可以包含一个ICollection,因为狗可以出现在多个事件中。
using (var context = new DbContext())
{
var results = context.Database.ExecuteStoreQuery<SomeResultDto>("SELECT * .... JOIN ... ");
}
using (var context = new DbContext())
{
context.Dogs.AddRange(dogs); // dogs being a list of dog entities
context.Results.AddRange(results); // events being a list of results entities
context.DogResults.AddRange(dogResults); // a list of the links
}
var dogResults = dogs.SelectMany( d => results.Select ( r => new DogResult { DogId = d.Id, ResultId = r.Id } ) );