简体   繁体   中英

Trouble with relationships in Entity Framework

I have a trouble with relationship in EF v4.I know that this question very popular, I tried to find something in Internet, but it didn't help. I have class Person that has one-to-one with Address(Person has Address)

class Person
{
public int PersonId{get;set;}
public string FisrtName{get; set;}
...
public int AddressId{get;set;}
public virtual Address Address{get;set;}
}
class Address
{
public int AddressId{get;set}
public string Street{get;set;}
...
}

I assumed that it was one-to-one relationship, I followed all conventions in EF v4. But when I create DB diagram of generated DB.I can't see any relations between Person and Address.I mean I see two tables without relations with keys on Person and key on Address Another tables with like this relations creates one-to-many with key on Account and infinity on Address, but code same.I see in designer only one-to-many reletions and some cases I can see any relations between tables tha must be. Please help me!Thank you for any help PS I thought it's trouble with designer when I add tables

If you are using code first you can customize the persistence mapping by using either a fluent code API or use attributes to refine the model. EF can resolve relationships through inference if you were to use a simple key name such as Id; in your case EF needs a hint that PersonID and AddressID are keys.

To use the attribute approach add a reference to System.ComponentModel.DataAnnotations in your project and a corresponding 'using System.ComponentModel.DataAnnotations;' in your source files as necessary. The following sample (EF 4.3.1) will generate a "one-to-many" relationship between the generated Addresses and Persons tables (you don't want a one-to-one in this case). After running the code, you will see the relationships in the SQL Server Database Diagram window.

class Program
{
    static void Main(string[] args)
    {
        using (ContactsEntities entities = new ContactsEntities())
        {
            Address doeaddress = new Address() { Street = "1 Broadway", ZipCode = "01234" };
            Address doeaddress2 = new Address() { Street = "2 Broadway", ZipCode = "01234" };
            entities.Addresses.Add(doeaddress);
            entities.Persons.Add(new Person() { FirstName = "Jane", LastName = "Doe", Address = doeaddress });
            entities.Persons.Add(new Person() { FirstName = "John", LastName = "Doe", Address = doeaddress });
            entities.Persons.Add(new Person() { FirstName = "Jim", LastName = "Doe", Address = doeaddress2 });
            entities.SaveChanges(); 
        }
        Console.WriteLine("Press Enter to exit...");
        Console.ReadLine();

    }
}

[Table("Addresses")]
public partial class Address
{
    public Address()
    {
        this.Persons = new HashSet<Person>();
    }
    [Key]
    public int AddressID { get; set; }
    [Required]
    public string Street { get; set; }
    [RegularExpression(@"^(\d{5}-\d{4}|\d{5}|\d{9})$")]
    [Required]
    public string ZipCode { get; set; }

    public virtual ICollection<Person> Persons { get; set; }
}

[Table("Persons")]
public partial class Person
{
    [Key]
    public int PersonID { get; set; }
    public int AddressID { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    [ForeignKey("AddressID")]
    public virtual Address Address { get; set; }
}

public partial class ContactsEntities : DbContext
{
    public DbSet<Address> Addresses { get; set; }
    public DbSet<Person> Persons { get; set; }
}

Based on feedback, here is an example of a one-to-one (actually a one-to-zero-or-one) relationship. I've used the fluent API to set the relationships in the OnModelCreating override. In this scenario a person can have at most one photo row. In practice this might be useful if the Photos table contained one or more large byte arrays to hold image data; I'm using a string to represent a link to an image for clarity.

    static void Main(string[] args)
    {
        using (ContactsEntities entities = new ContactsEntities())
        {

            entities.Persons.Add(new Person() { FirstName = "Jane", LastName = "Doe", Photo = new Photo() { PhotoLink = "/images/jane.jpg" } });
            entities.Persons.Add(new Person() { FirstName = "John", LastName = "Doe" }); // no photo
            entities.Persons.Add(new Person() { FirstName = "Joe", LastName = "Smith", Photo = new Photo() { PhotoLink = "/images/joe.jpg", ThumnbnailLink = "/images/thumbs/joe.jpg" } });

            // note that the following is not allowed based on the defined RI rules - will fail on call to SaveChanges:
            // entities.Photos.Add(new Photo() { PhotoLink = "/images/as.jpg" });

            entities.SaveChanges();

            foreach (Person person in entities.Persons)
            {
                Console.WriteLine("{0} {1} {2}", person.FirstName, person.LastName, person.Photo == null ? "missing photo" : person.Photo.PhotoLink);
            } 
        }

        Console.WriteLine("Press Enter to exit...");
        Console.ReadLine();

    }
}

public partial class ContactsEntities : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // a Person may have at most one Photo
        modelBuilder.Entity<Person>().HasOptional<Photo>(p => p.Photo);
        // a Photo is dependant on a Person (non-nullable FK constraint)
        modelBuilder.Entity<Photo>().HasRequired<Person>(p => p.Person);
        base.OnModelCreating(modelBuilder);
    }
    public DbSet<Photo> Photos { get; set; }
    public DbSet<Person> Persons { get; set; }
}

[Table("Photos")]
public partial class Photo
{
    [Key]
    public int PhotoID { get; set; }
    [Required]
    public string PhotoLink { get; set; }
    public string ThumnbnailLink { get; set; }
    public virtual Person Person { get; set; }
}

[Table("Persons")]
public partial class Person
{
    [Key]
    public int PersonID { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }

    public virtual Photo Photo { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM