我有这三个实体:
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; }
}
我之前一直在这里获得帮助,以便像这样设置它。 Entity Framework errors when trying to create many-to-many relationship
所以现在的方式我想result
是将这些类包含外键与其他两个表绑定在一起的“粘合剂”。
我几天来一直试图实现的目标是:
假设我创建了一个这样的事件:
[HttpPost]
public ActionResult CreateEvent(Event newEvent)
{
newEvent.EventDate = newEvent.EventDate.ToString();
_ef.AddEvent(newEvent);
return View();
}
现在我想下一步是为这个事件添加一个狗列表,为了做到这一点,我需要以某种方式使用我的结果类,因为那是“胶水”类。如果我在这里走得正确,请告诉我。
答案 0 :(得分:1)
我只是用流利的方法做到这一点(当我在学习的时候,我发现你可以用流利的方式做所有事情,但没有注释,所以我没有看过它们),以下内容创造了多对多我的Unit
实体和我的{{1}}实体:
UnitService
此代码位于modelBuilder.Entity<Unit>()
.HasMany<UnitService>(u => u.Services)
.WithMany(us => us.Units);
方法中。
在您的情况下,protected override void OnModelCreating(DbModelBuilder modelBuilder)
为Event
而Unit
为Dog
。
UnitService
答案 1 :(得分:1)
如你所做的那样,做很多很多关系并不是一个好主意。 See here
为了获得适当的多对多关系,以适当的方式映射到数据库中,并没有陷阱,我会这样尝试:
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 });
}
看起来有点讨厌,但它会返回一个包含Dog
及其相关Result
的匿名对象列表。但显然最好在存储过程中执行此操作:
using (var context = new DbContext())
{
var results = context.Database.ExecuteStoreQuery<SomeResultDto>("SELECT * .... JOIN ... ");
}
这更干净,因为您使用的是SQL。
这是处理它的一种更复杂的方式。但性能要高得多,特别是如果你完全理解实体框架如何执行LINQ。
显然,如果你想创建这些链接:
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
}
完全取决于您如何创建这些链接。要将其转换为sproc,您还需要创建一些自定义的用户定义表类型,并将它们用作表值参数。
var dogResults = dogs.SelectMany( d => results.Select ( r => new DogResult { DogId = d.Id, ResultId = r.Id } ) );
这是一个LINQ查询的野兽,基本上它会得到每只狗并将其链接到每个结果。在LinqPad中运行它并Dump
值。