实体框架代码首先是一对零或具有单独身份的关系

时间:2019-01-21 09:58:43

标签: entity-framework foreign-keys ef-code-first multiplicity

我有两个这样的课程:

public class Event
{
    [Key]
    [Required]
    public long Id { get; set; }

    [InverseProperty("Event")          
    public virtual Record Record{ get; set; }
}


public class Record
{
    [Key]
    [Required]
    public int Id { get; set; }

    [ForeignKey("Event")]
    public long? EventId { get; set; }

    public virtual Event Event{ get; set; }
}

但是,通过此设置我得到了预期的多重性错误。我要结束的是:

  • 没有记录的现有事件

  • 记录现有事件而没有事件

  • 与记录一起存在的事件(并在记录中存储事件ID)

有可能吗?我必须使用FluentApi而不是Data Annotations吗?

我不想在“事件”表中添加任何字段或键。

2 个答案:

答案 0 :(得分:1)

在EF 6.x中,您必须使用Fluent API进行如下配置:

import React, { Component } from 'react';
import { fade } from '@material-ui/core/styles/colorManipulator';
import { withStyles } from '@material-ui/core/styles';
import { connect } from 'react-redux';
import AuthA from '../store/actions/AuthA';
import { withRouter } from 'react-router-dom';
import '../Navbar.css';
import NavbarV from './NavbarV';
import PropTypes from 'prop-types';
import axios from 'axios';

class NavbarC extends Component {

  constructor(props){
    super(props);
     this.state = {
       client:[]
    }
  }


  componentWillMount(){
    this.getUser();
  }

  getUser(){
 axios.get (`http://localhost:3002/api/clients/${localStorage.getItem("userId")}?access_token=${localStorage.getItem("token")}`)
    .then(res => {
      this.setState({client: res.data}, () => {
        console.log(this.state)
      })
    })
  }

shouldComponentUpdate(nextState){
  return (this.state.client.firstName !== nextState.firstName || 
this.state.client.lastName !== nextState.lastName);
}

  componentWillUpdate(){
    this.getUser();
    console.log(this.state)
  }

  logout = () => {
    this.props.authfn.logout();
  };

    render() {

        return(
            <NavbarV logout = {this.logout}
           firstName={this.state.client.firstName}
           lastName={this.state.client.lastName}
           userId={this.props.userId}
            auth = {this.props.auth}
            classes={this.props.classes}/>
        )
    }
}

NavbarC.propTypes = {
  auth: PropTypes.bool.isRequired,
  firstName: PropTypes.string.isRequired,
  lastName: PropTypes.string.isRequired
};

const mapStateToProps = (state) => {
  return {
    auth: state.AuthR.auth,
    firstName: state.AuthR.firstName,
    lastName: state.AuthR.lastName,
    userId: state.AuthR.userId
  };
};

const mapDispatchToProps = dispatch => {
  return {
    authfn: AuthA(dispatch)
  }
};

export default connect(mapStateToProps, mapDispatchToProps) (withStyles(styles)(withRouter(NavbarC)));

在EF Core中,您当前的模型设置已经足够好!不需要做任何其他事情。

答案 1 :(得分:1)

您是正确的,仅给关系的两侧之一提供了外键。我首先认为双方都需要一个可为空的外键。但是,如果您愿意这样做,则事件1可能具有记录2的外键,而事件3则具有记录4的外键,等等。

显然,在这些情况下,两侧中只有一个具有外键。

看着configure one-to-zero-or-one relation,我发现以下内容就足够了:

class Event
{
    public long Id { get; set; }
    public string Name { get; set; }

    // Every Event has zero or one Record
    public virtual Record Record { get; set; }
}
class Record
{
    public long Id { get; set; }
    public string Name { get; set; }

    // Every Record has zero or one Event
    public virtual Event Event { get; set; }
}

和DbContext:

class OneToOneContext : DbContext
{
    public OneToOneContext(): base("OneToOneDemo"){}

    public DbSet<Event> Events { get; set; }
    public DbSet<Record> Records { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Record>()
            .HasOptional(record => record.Event)
            .WithOptionalDependent(ev => ev.Record)
            .WillCascadeOnDelete(false);
    }
}

流利的API通知模型构建者每个记录都有零个或一个事件,零个或一个记录。记录被声明为依赖。这样可以确保Record在此关系中具有异国情调。

请注意,我不必添加任何其他属性。因为我遵循code first conventions实体框架,所以能够检测到主键和表之间的关系。

我能够添加:不带记录的事件,不带事件的记录,带记录的事件和带事件的记录:

using (var dbContext = new OneToOneContext())
{
    dbContext.Events.Add(new Event { Name = "Event without Record"});
    dbContext.Records.Add(new Record { Name = "Record without Event" });

    dbContext.Events.Add(new Event
    {
        Name = "Event A with Record",
        Record = new Record { Name = "Record of Event A" },
    });

    dbContext.Records.Add(new Record
    {
        Name = "Record B with Event",
        Event = new Event { Name = "Event of Record B" },
    });

    dbContext.SaveChanges();
}