Entity Framework 6.1.2:零或一对多

Entity Framework 6.1.2: Zero or One to Many

以下代码解析 XML 并将值存储到 Entity Framework 对象中,最终在 SQL 数据库中结束:

Program.cs:

namespace locationProject
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument xml = XDocument.Load("locationDoc.xml");
            XNamespace cm = "http://somenamespace.com/cm";

            List<Location> locationColl = new List<Location>();
            List<Event> eventColl = new List<Event>();
            locationModelContainer context = new locationModelContainer();

            var i = 0;
            var i2 = 0;

            foreach (var continent in xml.Descendants(cm + "Continent"))
            {
                Location l = new Location();
                locationColl.Add(l);

                locationColl[i].Continent = (string)continent.Element(cm + "Name");

                foreach (var country in continent.Elements(cm + "Country"))
                {
                    locationColl[i].Country = (string)country.Element(cm + "Name");

                    foreach (var city in country.Elements(cm + "City"))
                    {
                        locationColl[i].City = (string)city.Element(cm + "Name");

                        context.Locations.Add(locationColl[i]);

                        foreach (var events in city.Elements(cm + "Event"))
                        {
                            Event e = new Event();
                            eventColl.Add(e);

                            eventColl[i2].Name = (string)events.Element(cm + "Name");
                            eventColl[i2].Date = (string)events.Element(cm + "Date");

                            context.Events.Add(eventColl[i2]);
                            i2++;
                        }
                        i++;
                    }
                }
            }
            context.SaveChanges();
        }
    }
}

locationDoc.xml:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:cm="http://somenamespace.com/cm">
   <cm:Continent>
      <cm:Name>Europe</cm:Name>
      <cm:Country>
         <cm:Name>United Kingdom</cm:Name>
         <cm:City>
            <cm:Name>London</cm:Name>
            <cm:Event>
            <cm:Name>Event1</cm:Name>
            <cm:Date>01/01/2020</cm:Date>
            </cm:Event>
            <cm:Event>
            <cm:Name>Event2</cm:Name>
            <cm:Date>01/01/2020</cm:Date>
            </cm:Event>
         </cm:City>
      </cm:Country>
   </cm:Continent>
      <cm:Continent>
      <cm:Name>Europe</cm:Name>
      <cm:Country>
         <cm:Name>France</cm:Name>
         <cm:City>
            <cm:Name>Paris</cm:Name>
            <cm:Event>
            <cm:Name>Event3</cm:Name>
            <cm:Date>01/01/2020</cm:Date>
            </cm:Event>
            <cm:Event>
            <cm:Name>Event4</cm:Name>
            <cm:Date>01/01/2020</cm:Date>
            </cm:Event>
         </cm:City>
      </cm:Country>
   </cm:Continent>
      <cm:Continent>
      <cm:Name>Europe</cm:Name>
      <cm:Country>
         <cm:Name>Germany</cm:Name>
         <cm:City>
            <cm:Name>Berlin</cm:Name>
            <cm:Event>
            <cm:Name>Event5</cm:Name>
            <cm:Date>01/01/2020</cm:Date>
            </cm:Event>
            <cm:Event>
            <cm:Name>Event6</cm:Name>
            <cm:Date>01/01/2020</cm:Date>
            </cm:Event>
         </cm:City>
      </cm:Country>
   </cm:Continent>
</feed>

Location.cs:

namespace locationProject
{
    using System;
    using System.Collections.Generic;

    public partial class Location
    {
        public Location()
        {
            this.Events = new HashSet<Event>();
        }

        public int LocationID { get; set; }
        public string Continent { get; set; }
        public string Country { get; set; }
        public string City { get; set; }

        public virtual ICollection<Event> Events { get; set; }
    }
}

Event.cs:

    namespace locationProject
    {
        using System;
        using System.Collections.Generic;

        public partial class Event
        {
            public int EventID { get; set; }
            public Nullable<int> Location_LocationID { get; set; }
            public string Name { get; set; }
            public string Date { get; set; }

            public virtual Location Location { get; set; }
        }
    }

locationModelContainer:

public partial class locationModelContainer : DbContext
{
    public locationModelContainer()
        : base("name=locationModelContainer")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<Location> Locations { get; set; }
    public virtual DbSet<Event> Events { get; set; }
    }
}

locationModel.edmx.sql:

SET QUOTED_IDENTIFIER OFF;
GO
USE [Locations];
GO
IF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]');
GO

IF OBJECT_ID(N'[dbo].[FK_LocationEvent]', 'F') IS NOT NULL
    ALTER TABLE [dbo].[Events] DROP CONSTRAINT [FK_LocationEvent];
GO

IF OBJECT_ID(N'[dbo].[Locations]', 'U') IS NOT NULL
    DROP TABLE [dbo].[Locations];
GO
IF OBJECT_ID(N'[dbo].[Events]', 'U') IS NOT NULL
    DROP TABLE [dbo].[Events];
GO

CREATE TABLE [dbo].[Locations] (
    [LocationID] int IDENTITY(1,1) NOT NULL,
    [Continent] nvarchar(max)  NOT NULL,
    [Country] nvarchar(max)  NOT NULL,
    [City] nvarchar(max)  NOT NULL
);
GO

CREATE TABLE [dbo].[Events] (
    [EventID] int IDENTITY(1,1) NOT NULL,
    [Location_LocationID] int  NULL,
    [Name] nvarchar(max)  NOT NULL,
    [Date] nvarchar(max)  NOT NULL
);
GO

ALTER TABLE [dbo].[Locations]
ADD CONSTRAINT [PK_Locations]
    PRIMARY KEY CLUSTERED ([LocationID] ASC);
GO

ALTER TABLE [dbo].[Events]
ADD CONSTRAINT [PK_Events]
    PRIMARY KEY CLUSTERED ([EventID] ASC);
GO

ALTER TABLE [dbo].[Events]
ADD CONSTRAINT [FK_LocationEvent]
    FOREIGN KEY ([Location_LocationID])
    REFERENCES [dbo].[Locations]
        ([LocationID])
    ON DELETE NO ACTION ON UPDATE NO ACTION;
GO

CREATE INDEX [IX_FK_LocationEvent]
ON [dbo].[Events]
    ([Location_LocationID]);
GO

使用一对多关系(一个位置到多个事件)按预期工作。 Location_LocationID 外键被相关的 LocationID 填充。

尽管如此,如上代码所示,我的预期设计是使用零或一对多关系(零或一个位置到多个事件)。但是,使用此关系不会填充 Location_LocationID 外键,而是在保存到数据库时,所有 Location_LocationID 字段都包含 NULL

谁能解释一下为什么他们没有使用这种关系填充?提前致谢!

您目前没有为任何活动设置地点。所以它当然总是空的。您也只是在每个大陆创建一个位置。将创建位置的位置移动到枚举城市的位置。

foreach (var continent in xml.Descendants(cm + "Continent"))
{
     var continent = (string)continent.Element(cm + "Name");

     foreach (var country in continent.Elements(cm + "Country"))
     {
         var country = (string)country.Element(cm + "Name");

         foreach (var city in country.Elements(cm + "City"))
         {
             Location l = new Location();
             l.Continent = continent;
             l.Country = country;
             l.City = (string)city.Element(cm + "Name");
             context.Locations.Add(l);
             locationColl.Add(l);

             foreach (var events in city.Elements(cm + "Event"))
             {
                 Event e = new Event();
                 eventColl.Add(e);

                 e.Location = l;
                 eventColl[i2].Name = (string)events.Element(cm + "Name");
                 eventColl[i2].Date = (string)events.Element(cm + "Date");

                 context.Events.Add(eventColl[i2]);
                 i2++;
             }
             i++;
         }
     }
 }
 context.SaveChanges();