Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 设置可选:必需的关系实体框架-fluent API_C# 4.0_Entity Framework 4.1_Code First - Fatal编程技术网

C# 4.0 设置可选:必需的关系实体框架-fluent API

C# 4.0 设置可选:必需的关系实体框架-fluent API,c#-4.0,entity-framework-4.1,code-first,C# 4.0,Entity Framework 4.1,Code First,我有一个用户配置文件关系,用户可以(可选)关联一个配置文件。 在数据库中,PROFILES表与USERS表之间有一个FK(FK可为空) 我想用EF fluent API设置它。我设法做到了,一切正常,但问题是我不能将概要文件中的FK作为类中的属性 因此,在DB中,我有: [USERS] ID uniqueidentifier PK not null [PROFILES] ID uniqueidentifier PK not null USERID uniqueidentifer FK null

我有一个用户配置文件关系,用户可以(可选)关联一个配置文件。 在数据库中,PROFILES表与USERS表之间有一个FK(FK可为空)

我想用EF fluent API设置它。我设法做到了,一切正常,但问题是我不能将概要文件中的FK作为类中的属性

因此,在DB中,我有:

[USERS]
ID uniqueidentifier PK not null

[PROFILES]
ID uniqueidentifier PK not null
USERID uniqueidentifer FK null
在代码中,我有:

public class User { public virtual Profile { get; set; } }
public class Profile { public virtual User { get; set; } }
请注意,DB中的列名不符合EF命名约定

我可以按如下方式配置EF:

HasOptional(u => u.Profile).WithRequired(p => p.User).Map(m => m.MapKey("USERID")).WillCascadeOnDelete();
或者反过来说:

HasRequired(p => p.User).WithOptional(u => u.Profile).Map(m => m.MapKey("USERID")).WillCascadeOnDelete();
在这种情况下,我真的需要使用MapKey映射FK(因为EF使用的命名约定),这似乎是一个不允许我在模型中添加FK的问题

因此,我不能:

public class Profile { public virtual User { get; set; } public Guid? UsreId { get; set; } }
有人知道我怎样才能做到这一点吗

编辑 问题的根源是,如果我不使用.Map(m=>m.MapKey(“USERID”))方法,约定会破坏关系(它期望FK是User_Id),这基本上就像在没有任何参数的情况下使用它一样。如果我使用.Map(m=>m.MapKey(“USERID”))方法,那么它表示我已经将USERID作为模型中的属性(来自内联帮助:配置关系以使用对象模型中未公开的外键属性)和表可以通过指定配置操作进行自定义。如果指定了空配置操作,则将按照约定生成列名

糟糕透了

编辑2设法修复了它(基本上是采用另一种方法)。 将表更改为:

[USERS]
ID uniqueidentifier PK not null

[PROFILES]
-- ID uniqueidentifier PK not null (removed the PK)
USERID uniqueidentifer PK not null, FK not null -- (the PK is also the FK)
在运行SQL探查器并查看在那里运行的查询之后,我来到这里。 根据用户ID查询每个用户的optionl配置文件。WARE条款类似于:

SELECT *
FROM PROFILES
WHERE ID = @userId -- ID was the PK
所以我发现PROFILES表中的PK在这种情况下也必须是FK,并且映射可以保持简单:

HasOptional(u => u.Profile).WithRequired(p => p.User);
还是在另一端

HasRequired(p => p.User).WithOptional(u => u.Profile);
这一条很有帮助:


干杯

您需要将重点放在正确映射实体本身上,然后关系就可以正常工作了。关于关键点的约定如下:

  • 如果实体有一个名为Id的属性,它将用作键
  • 如果存在EntityId(例如UserId)属性,则该属性就是密钥
  • 否则,您需要指定键属性是什么
  • 至于key属性对应于数据库中的哪个列,可以使用property()和HasColumnName()方法指定

    完成后,您就不必担心关系映射中的映射键(至少在您的情况下是一对一映射)

    至于关系映射,您不必同时从用户和概要文件定义关系。一旦定义了一种关系,就会推断出另一种关系。这也可以保持代码的整洁

    下面的代码应该可以帮助您理解整个过程

    class Program
    {
        static void Main(string[] args)
        {
            // replace your connection string here
            using (var userContext = new UserContext("UserProfile"))
            {
                var u = new User { UserId = Guid.NewGuid(), Name = "John", Profile = new Profile() { ProfileId = Guid.NewGuid(), SomeValue = "x" } };
    
                userContext.Users.Add(u);
                userContext.SaveChanges();
    
                var users = userContext.Users.ToList();
    
                foreach (var user in users)
                {
                    Console.WriteLine(user.Name);
                    if (user.Profile != null)
                    {
                        Console.WriteLine(user.Profile.ProfileId);
                    }
                }
    
                var profiles = userContext.Profiles.Where(p => p.User.Name == "John").ToList();
            }
        }
    }
    
    public class UserContext : DbContext
    {
        public UserContext(string connectionString)
            : base(connectionString)
        {
        }
    
        public DbSet<User> Users { get; set; }
    
        public DbSet<Profile> Profiles { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            modelBuilder.Entity<User>().Property(u => u.UserId).HasColumnName("ID");
            modelBuilder.Entity<Profile>().Property(p => p.ProfileId).HasColumnName("ID");
    
            modelBuilder.Entity<User>().HasOptional(u => u.Profile).WithRequired(p => p.User);
        }
    }
    
    public class User
    {
        public Guid UserId { get; set; }
    
        public string Name { get; set; }
    
        public Profile Profile { get; set; }
    }
    
    public class Profile
    {
        public Guid ProfileId { get; set; }
    
        public User User { get; set; }
    
        public string SomeValue { get; set; }
    }
    
    类程序
    {
    静态void Main(字符串[]参数)
    {
    //在此处替换连接字符串
    使用(var userContext=newusercontext(“UserProfile”))
    {
    var u=新用户{UserId=Guid.NewGuid(),Name=“John”,Profile=newprofile(){ProfileId=Guid.NewGuid(),SomeValue=“x”};
    userContext.Users.Add(u);
    userContext.SaveChanges();
    var users=userContext.users.ToList();
    foreach(用户中的var用户)
    {
    Console.WriteLine(用户名);
    if(user.Profile!=null)
    {
    Console.WriteLine(user.Profile.ProfileId);
    }
    }
    var profiles=userContext.profiles.Where(p=>p.User.Name==“John”).ToList();
    }
    }
    }
    公共类UserContext:DbContext
    {
    公共用户上下文(字符串连接字符串)
    :基本(连接字符串)
    {
    }
    公共数据库集用户{get;set;}
    公共数据库集配置文件{get;set;}
    模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
    {
    基于模型创建(modelBuilder);
    modelBuilder.Entity().Property(u=>u.UserId).HasColumnName(“ID”);
    modelBuilder.Entity().Property(p=>p.ProfileId).HasColumnName(“ID”);
    modelBuilder.Entity();
    }
    }
    公共类用户
    {
    公共Guid用户标识{get;set;}
    公共字符串名称{get;set;}
    公共配置文件{get;set;}
    }
    公共班级简介
    {
    公共Guid配置文件ID{get;set;}
    公共用户{get;set;}
    公共字符串SomeValue{get;set;}
    }
    
    你说的是对的。问题是我想在Profile类中有一个UserId属性(映射到数据库中的FK列)和User属性。