Entity framework 首先在EF 5代码中将数据库记录反编译为主/详细信息

Entity framework 首先在EF 5代码中将数据库记录反编译为主/详细信息,entity-framework,ef-code-first,entity-framework-5,code-first,Entity Framework,Ef Code First,Entity Framework 5,Code First,我有一个具有以下结构的遗留数据库表 CREATE TABLE [dbo].[MASTER_PROJECT]( [DATA_ID] [bigint] IDENTITY(1,1) NOT NULL, ...... [GENRE_DATA_ID] [bigint] NULL, [ADDITIONAL_GENRE_DATA_ID] [bigint] NULL, [ADDITIONAL_GENRE_2_DATA_ID] [bigint] NULL ) 我希望使

我有一个具有以下结构的遗留数据库表

CREATE TABLE [dbo].[MASTER_PROJECT](
    [DATA_ID] [bigint] IDENTITY(1,1) NOT NULL,
    ......
    [GENRE_DATA_ID] [bigint] NULL,  
    [ADDITIONAL_GENRE_DATA_ID] [bigint] NULL,
    [ADDITIONAL_GENRE_2_DATA_ID] [bigint] NULL )
我希望使用EF5(代码优先)绘制以下类

但这会生成一个错误,即t.Genres[0]不是有效的属性。(这是有道理的)

你知道我该怎么做吗?
谢谢

您想要做的事情和EF无关-您需要使用返回项集合的新方法或属性实现此实体的部分类。当然,您需要使用各种类型数据ID属性中的值填充此集合。例如:

public ICollection<Genre?> GenreDataIDs
{
    get 
    {
        var col = new List<Genre?>() { GENRE_DATA_ID_NavProperty, ADDITIONAL_GENRE_DATA_ID_NavProperty, ..., ADDITION_GENRE_N_DATA_ID_NavProperty };

        return col;
    }
}
public-ICollection-genredataid
{
得到
{
var col=new List(){GENRE_DATA_ID_NavProperty,ADDITION_GENRE_DATA_ID_NavProperty,…,ADDITION_GENRE_N_DATA_ID_NavProperty};
返回列;
}
}
您的导航属性可能被命名为Genre1、Genre2;为了便于说明,我只是在列名中添加了_NavProperty


如果您想使用集合来更新底层DB记录,它会变得更复杂(最简单的实现是实现SetGenreDataID(int index,int?value)方法)

在Moho的帮助下,我终于得到了想要的结果

您还需要确保包含此域实体的项目授予映射项目可见的内部构件。(在AssemblyInfo.cs中)

实体定义

public class Project 
{
        private ObservableCollection<Genre> _genres;
        protected internal virtual Genre Genre1 { get; set; }
        protected internal virtual Genre Genre2 { get; set; }
        protected internal virtual Genre Genre3 { get; set; }

        public IList<Genre> Genres
        {
            get
            {
                if (_genres == null)
                {
                    _genres = new ObservableCollection<Genre>(new[] {Genre1, Genre2, Genre3});
                    _genres.CollectionChanged += GenresCollectionChangedHandler;
                }
                return _genres;
            }
        }
        private void SetGenreByIndex(int index, Genre g)
        {
            switch (index)
            {
                case 0: Genre1 = g; break;
                case 1: Genre2 = g; break;
                case 2: Genre3 = g; break;
            }
        }

        private void GenresCollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
        {                
            _genres.CollectionChanged -= GenresCollectionChangedHandler;

            int max = 3;
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (_genres.Count > max)
                    {
                        _genres.RemoveAt(max);
                        _genres.CollectionChanged += GenresCollectionChangedHandler;
                        throw new IndexOutOfRangeException("Not allowed to store more than 3 genres.");
                    }
                    SetGenreByIndex(_genres.Count - 1, e.NewItems[0] as Genre);
                    break;

                case NotifyCollectionChangedAction.Replace:
                    for (var i = 0; i < e.NewItems.Count; i++)
                        SetGenreByIndex(i + e.NewStartingIndex, e.NewItems[i] as Genre);
                    break;

                case NotifyCollectionChangedAction.Reset:
                    Genre1 = null;
                    Genre2 = null;
                    Genre3 = null;
                    _genres.Clear();
                    break;
            }
            _genres.CollectionChanged += GenresCollectionChangedHandler;
        }
}
这里有一个测试方法来确保它的工作

[TestClass]
public class ProjectUnitTests
{
    [TestMethod]
    public void SwapGenresInListAndSaveTest()
    {
        //Arrange
        Genre original1 = null;
        Genre original2 = null;

        using (var context = new MyContext())
        {
            context.Configuration.LazyLoadingEnabled = true;

            //ACT
            var project = context.Projects.Find(2341);
            original1 = project.Genres[0];
            original2 = project.Genres[1];

            genres[0] = original2;
            genres[1] = original1;

            //Save to DB
            context.SaveChanges();
        }

        //ASSERT
        using (var context = new MyContext())
        {
            var project1 = context.Projects.Find(2341);

            //ASSERT
            Assert.IsNotNull(project1);
            Assert.IsNotNull(project1.Genres);
            Assert.AreEqual(3, project1.Genres.Count);
            Assert.AreEqual(original2.DataId, project1.Genres[0].DataId);
            Assert.AreEqual(original1.DataId, project1.Genres[1].DataId);
        }
    }
}

谢谢你的回答,但我仍然不确定我是否理解你的意思。您是说将属性GenreDataIDs添加到主项目类吗?那么我该如何将这些数据ID映射到相关的映射类型类,而不是int列表?您可以返回列表;同样的原则是,您必须自己构造ICollection。我会编辑答案好的,我明白你的意思了。因此,该项目将有4个公共财产,Genre1、Genre2、Genre3和IListGenres。这正是我试图避免的,但我想这是没有办法的。谢谢你的帮助!
[assembly: InternalsVisibleTo("YOUR.MAPPING.PROJECT")]
public class Project 
{
        private ObservableCollection<Genre> _genres;
        protected internal virtual Genre Genre1 { get; set; }
        protected internal virtual Genre Genre2 { get; set; }
        protected internal virtual Genre Genre3 { get; set; }

        public IList<Genre> Genres
        {
            get
            {
                if (_genres == null)
                {
                    _genres = new ObservableCollection<Genre>(new[] {Genre1, Genre2, Genre3});
                    _genres.CollectionChanged += GenresCollectionChangedHandler;
                }
                return _genres;
            }
        }
        private void SetGenreByIndex(int index, Genre g)
        {
            switch (index)
            {
                case 0: Genre1 = g; break;
                case 1: Genre2 = g; break;
                case 2: Genre3 = g; break;
            }
        }

        private void GenresCollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
        {                
            _genres.CollectionChanged -= GenresCollectionChangedHandler;

            int max = 3;
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (_genres.Count > max)
                    {
                        _genres.RemoveAt(max);
                        _genres.CollectionChanged += GenresCollectionChangedHandler;
                        throw new IndexOutOfRangeException("Not allowed to store more than 3 genres.");
                    }
                    SetGenreByIndex(_genres.Count - 1, e.NewItems[0] as Genre);
                    break;

                case NotifyCollectionChangedAction.Replace:
                    for (var i = 0; i < e.NewItems.Count; i++)
                        SetGenreByIndex(i + e.NewStartingIndex, e.NewItems[i] as Genre);
                    break;

                case NotifyCollectionChangedAction.Reset:
                    Genre1 = null;
                    Genre2 = null;
                    Genre3 = null;
                    _genres.Clear();
                    break;
            }
            _genres.CollectionChanged += GenresCollectionChangedHandler;
        }
}
public class ProjectConfiguration
{
    public ProjectConfiguration()
    {
        // ...
        // GENRES collection
        Ignore(t => t.Genres);
        HasOptional(t => t.Genre1).WithMany().Map(m => m.MapKey("GENRE_DATA_ID"));
        HasOptional(t => t.Genre2).WithMany().Map(m => m.MapKey("GENRE_DATA_ID_1"));
        HasOptional(t => t.Genre3).WithMany().Map(m => m.MapKey("GENRE_DATA_ID_2"));
    }
}
[TestClass]
public class ProjectUnitTests
{
    [TestMethod]
    public void SwapGenresInListAndSaveTest()
    {
        //Arrange
        Genre original1 = null;
        Genre original2 = null;

        using (var context = new MyContext())
        {
            context.Configuration.LazyLoadingEnabled = true;

            //ACT
            var project = context.Projects.Find(2341);
            original1 = project.Genres[0];
            original2 = project.Genres[1];

            genres[0] = original2;
            genres[1] = original1;

            //Save to DB
            context.SaveChanges();
        }

        //ASSERT
        using (var context = new MyContext())
        {
            var project1 = context.Projects.Find(2341);

            //ASSERT
            Assert.IsNotNull(project1);
            Assert.IsNotNull(project1.Genres);
            Assert.AreEqual(3, project1.Genres.Count);
            Assert.AreEqual(original2.DataId, project1.Genres[0].DataId);
            Assert.AreEqual(original1.DataId, project1.Genres[1].DataId);
        }
    }
}