我有一些基本的数据库设计问题,我希望在我完成并绘制所有数据库关系之前清除它们。
问题1
我有两个表,第一个将包含第二个表。我将使用实体框架,并希望从table1
访问table2
,从table2
访问table1
。
我的想法是拥有从table1
到table2
的外键,以及从table2
到table1
的外键。添加从table1
到table2
的链接似乎有效。但是,当我尝试添加第二个链接(从table2
到table1
)时,MySQL Workbench会添加两个链接而不是一个。我在想我做错了,因为我的理解是它应该只添加一个链接。我的设计是错误的,还是应该删除正在添加的第二个链接?
问题2
接下来,我正在尝试实现一个连接表。 table1
的实例可以有许多table2
实例,反之亦然,因此连接表似乎是实现此目的的必要结构。 MySQL允许我创建Identifying Relationship
或Non-Identifying Relationship
,我不确定要使用哪个。有什么想法吗?
如果需要进一步澄清,请告诉我。
答案 0 :(得分:1)
正如ypercube和JesseB指出的那样,我认为你所需要的只是一个1..n关系。
使用Entity Framework 4.1(和POCO Code First),您只需要一张声明此关系的地图,例如
this.HasRequired(t => t.Image)
.WithMany(t => t.Words)
.HasForeignKey(d => d.ImageId);
请在这里找到完整且有效的代码。如果启动它将创建一个包含所有所需外键的数据库。您将在image_id
表中看到您需要的唯一外键是words
。实体框架能够将Word
的集合注入任何Image
对象,而不依赖于任何其他外键。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WordAndImages.Entities;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
namespace WordAndImages
{
public class Word
{
public int Id { get; set; }
public int ImageId { get; set; }
public virtual Image Image { get; set; }
public string Value { get; set; }
}
public class Image
{
public int Id { get; set; }
public virtual List<Word> Words { get; set; }
public string Value { get; set; }
public Image()
{
Words = new List<Word>();
}
}
public class Context : DbContext
{
static Context()
{
Database.SetInitializer<Context>(null);
}
public DbSet<Word> Words { get; set; }
public DbSet<Image> Images { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new WordsMap());
}
}
public class WordsMap : EntityTypeConfiguration<Word>
{
public WordsMap()
{
this.HasRequired(t => t.Image)
.WithMany(t => t.Words)
.HasForeignKey(d => d.ImageId);
}
}
class Program
{
static void Main(string[] args)
{
#region Saving a Word with an Image
var context = new Context();
context.Database.Delete();
context.Database.CreateIfNotExists();
var word = new Word();
word.Value = "I'm a word";
var image = new Image();
image.Value = "I'm an image";
word.Image = image;
context.Words.Add(word);
context.SaveChanges();
#endregion
#region Accessing an Image from a Word and viceversa
var context2 = new Context();
var recovered_word = context2.Words.Where(w => w.Value == "I'm a word").FirstOrDefault();
Console.WriteLine(string.Format("I'm the word '{0}' and my image is '{1}'", word.Value, word.Image.Value));
var recovered_image = context2.Images.Where(w => w.Value == "I'm an image").FirstOrDefault();
Console.WriteLine(string.Format("I'm the image '{0}' and one of my images is '{1}'", recovered_image.Value, recovered_image.Words.First().Value));
Console.ReadLine();
#endregion
}
}
}
对于many-to-many
关系,只需使用
this.HasMany(a => a.Words)
.WithMany(z => z.Images)
.Map(m =>
m.ToTable("Images_Words").MapLeftKey("Word_id").MapRightKey("Image_id"));
并按以下方式修改您的课程
public class Word
{
public int Id { get; set; }
public virtual List<Image> Images { get; set; }
public string Value { get; set; }
public Word()
{
Images = new List<Image>();
}
}
public class Image
{
public int Id { get; set; }
public virtual List<Word> Words { get; set; }
public string Value { get; set; }
public Image()
{
Words = new List<Word>();
}
}
如果不使用旧数据库,我首先要设计域对象,然后让ORM创建表和外键。
如果您首选从数据库开始,请考虑扩展实体框架Power Tools CTP1,您可以从Extension Manager下载它:它能够从数据库生成POCO类。