实体框架关系

时间:2014-11-04 07:31:40

标签: 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<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是将这些类包含外键与其他两个表绑定在一起的“粘合剂”。

我几天来一直试图实现的目标是:

  1. 创建活动。
  2. 将狗添加到活动中。
  3. 将结果添加到参与choosenEvent的狗。
  4. 假设我创建了一个这样的事件:

    [HttpPost]
    public ActionResult CreateEvent(Event newEvent)
    {
        newEvent.EventDate = newEvent.EventDate.ToString();
        _ef.AddEvent(newEvent);
    
        return View();
    }
    

    现在我想下一步是为这个事件添加一个狗列表,为了做到这一点,我需要以某种方式使用我的结果类,因为那是“胶水”类。如果我在这里走得正确,请告诉我。

2 个答案:

答案 0 :(得分:1)

我只是用流利的方法做到这一点(当我在学习的时候,我发现你可以用流利的方式做所有事情,但没有注释,所以我没有看过它们),以下内容创造了多对多我的Unit实体和我的{​​{1}}实体:

UnitService

此代码位于modelBuilder.Entity<Unit>() .HasMany<UnitService>(u => u.Services) .WithMany(us => us.Units); 方法中。

在您的情况下,protected override void OnModelCreating(DbModelBuilder modelBuilder)EventUnitDog

哦ooops,你根本不需要那个,你的'join'表是你的结果表,在我的情况下我不关心连接表所以它全部隐藏。 也许是这样的:

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值。