我有一些基本的 DB 设计问题,我想在我完成并绘制所有 DB 关系之前弄清楚它们。
问题一
我有两个表,第一个表包含第二个表的一个实例。我将使用 Entity Framework ,并希望从 table2
访问 table1
,并从 table1
访问 table2
.
我的想法是有一个外键从table1
到table2
,另一个从table2
到table1
.添加从 table1
到 table2
的链接似乎有效。但是,当我尝试添加第二个链接(从 table2
到 table1
)时,MySQL Workbench 添加了两个链接而不是一个。我在想我做错了什么,因为据我所知,它应该只添加一个链接。是我的设计有误,还是我应该删除正在添加的第二个链接?
问题二
接下来,我将尝试实现一个连接表。 table1
的一个实例可以有多个 table2
的实例,反之亦然,因此连接表似乎是实现此目的的必要结构。 MySQL 允许我创建Identifying Relationship
或Non-Identifying Relationship
,但我不确定要使用哪个。有什么想法吗?
如果需要更多说明,请告诉我。
最佳答案
正如 ypercube 指出的那样和 JesseB我认为您只需要 1..n 关系。
使用 Entity Framework 4.1(和 POCO Code First),您所需要的只是一个声明此关系的映射,例如
this.HasRequired(t => t.Image)
.WithMany(t => t.Words)
.HasForeignKey(d => d.ImageId);
请在此处找到完整且有效的代码。如果启动,它将创建一个包含所有需要的外键的数据库。您会看到您需要的唯一外键是 words
表中的 image_id
。 Entity Framework 能够将 Word
的集合注入(inject)到任何 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
}
}
}
对于多对多
关系,只需使用像这样的映射
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 创建表和外键。
如果您更喜欢从数据库开始,请考虑扩展 Entity Framework Power Tools CTP1,您可以从 Extension Manager 下载它:它能够从数据库生成 POCO 类。
关于MySQL 数据库设计问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8460933/