我看过其他一些答案和许多文章,但是这个简单的部分仍然使我难以理解。我首先使用EF代码4.1,但很乐意迁移到新版本,如果这样做更容易。我有一个像这样的主要事实表:

namespace Spend.Models
{
    public class ExpenseItem
    {
        [Key]
        public String UniqueID_ERLineID { get; set; }
        public String ERNum { get; set; }
        public String ItemNum { get; set; }
        public String Parent_Expense_Item { get; set; }
        public String Card_Number { get; set; }
...


还有几个与ExpenseItems具有多对一关系的表:

public class ExpenseItemAccounting
{
    [Key]
    public String UniqueID_Accounting { get; set; }
    public String ERLineID { get; set; }
    public String ERNum { get; set; }
    public String ItemNum { get; set; }


如我们所见,第二个表中的ERLineID与第一个表中的UniqueID_ErLineID联接在一起,因此我通常依赖的“约定”不起作用。因此,我需要使用虚拟ICollection-但我希望它指定这些字段作为链接。任何帮助如何做到这一点表示赞赏。

PS。我目前无法重命名数据库字段。

@卢克:

我应用了您提到的更改,它们很有意义。但是,我得到以下错误:

System.Data.Entity.ModelConfiguration.ModelValidationException occurred
  Message=One or more validation errors were detected during model generation:

    System.Data.Edm.EdmAssociationType: : Multiplicity conflicts with the referential constraint in Role 'ExpenseItemAccounting_ExpenseItem_Target' in relationship 'ExpenseItemAccounting_ExpenseItem'. Because all of the properties in the Dependent Role are non-nullable, multiplicity of the Principal Role must be '1'.
    System.Data.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'ExpenseItemAccounting_ExpenseItem_Source' in relationship 'ExpenseItemAccounting_ExpenseItem'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be �1�.

  Source=EntityFramework
  StackTrace:
       at System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl(EdmModel model, XmlWriter writer)
       at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
       at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
       at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
       at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
       at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
       at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
       at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
       at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
       at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
       at System.Linq.Queryable.SelectMany[TSource,TCollection,TResult](IQueryable`1 source, Expression`1 collectionSelector, Expression`1 resultSelector)
       at EmailClient.Prog.getData() in C:\MF\Dropbox\Dev_LN_Projects\04_QA\EmailClient\EmailClient\Prog.cs:line 172
  InnerException:


这是在我尝试以下linq查询时出现的:

        var geee = (from e in db.ExpenseItems
                        from f in db.ExpenseItemFbtItems
                        where
                        e.Item_Transaction_Date.Value.Year == 2011 &&
                        e.Item_Transaction_Date.Value.Month == 8
                        select new { A = e.UniqueID_ERLineID, B = f.ERLineID.First() });


我实际上希望能够说出e.ExpenseItemAccounting.ItemNum之类的东西-我是否需要在ExpenseItem定义中添加一些内容才能实现此目的?

我的模型设置如下。 base.OnModelCreating通过intellisense出现,我尝试过使用/不使用它来获得相同的结果:

public class SpendDB : DbContext
{
    public DbSet<ExpenseAttachment> ExpenseAttachments {get; set; }
    public DbSet<ExpenseComment> ExpenseComments {get; set; }
    public DbSet<ExpenseItemAccounting> ExpenseAccountings {get; set; }
    public DbSet<ExpenseItemFbtItem> ExpenseItemFbtItems {get; set; }
    public DbSet<ExpenseItem> ExpenseItems {get; set; }
    public DbSet<ExpenseItemViolation> ExpenseItemViolations {get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<ExpenseItemAccounting>().HasOptional(e => e.ExpenseItem).WithMany().HasForeignKey(e => e.UniqueID_Accounting);
    }
}


也许我需要将虚拟ICollection放入ExpenseItem定义中?还是相反?例如,modelBuilder.Entity具有可选的ExpenseItemAccounting?对我来说,这听起来更直观,但我(显然)不太擅长此事,请带一点盐!

再次感谢

最佳答案

做这个:

public class ExpenseItemAccounting
{
    [Key]
    public String UniqueID_Accounting { get; set; }
    public ExpenseItem ExpenseItem{get;set;}
    public String ERLineID { get; set; }
    public String ERNum { get; set; }
    public String ItemNum { get; set; }
}


然后在您的modelBuilder中使用

modelBuilder.Entity<ExpenseItemAccounting>()
    .HasOptional(e => e.ExpenseItem).WithMany()
    .HasForeignKey(e => e.UniqueID_Accounting );


编辑:

要将导航属性配置为在另一端具有集合,您可以像这样简单地添加它

public class ExpenseItem
{
        [Key]
        public String UniqueID_ERLineID { get; set; }
        public String ERNum { get; set; }
        public String ItemNum { get; set; }
        public String Parent_Expense_Item { get; set; }
        public String Card_Number { get; set; }
        public ICollection<ExpenseItemAccounting> ExpenseItemAccountings{ get; set; }
}


然后通过如下修改模型构建器配置来进行连接:

 modelBuilder.Entity<ExpenseItemAccounting>()
     .HasOptional(e => e.ExpenseItem).WithMany(e=> e.ExpenseItems)
     .HasForeignKey(e => e.UniqueID_Accounting );


这将进行连接,以便ExpenseItem将具有所有子ExpensItemAccounting的列表,如果更有意义的话,您也可以添加单个版本,例如:

 public class ExpenseItem
    {
            [Key]
            public String UniqueID_ERLineID { get; set; }
            public String ERNum { get; set; }
            public String ItemNum { get; set; }
            public String Card_Number { get; set; }
            public ExpenseItemAccounting Parent_Expense_Item { get; set; }
    }


并使用modelBuilder进行配置:

modelBuilder.Entity<ExpenseItemAccounting>()
    .HasOptional(e => e.ExpenseItem)
    .WithOptionalDependent(e=>e.Parent_Expense_Item);


我认为,如果您还希望将FK引用连接起来(而不仅仅是导航属性),则需要在单独的语句中执行此操作,但那就麻烦了。

看一下有关导航属性的MSDN页面,以及如何使用modelBuilder,因为它有许多高级的好例子。

http://msdn.microsoft.com/en-us/library/hh295843(v=vs.103).aspx

关于c# - EF代码优先:定义外键,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9612611/

10-10 16:24