Rod
Rod

Reputation: 211

Create Composite Key and Unique - Security Multi tenant

In multi tenant application, we can force the ID that is in another tenant in input

In SQL Server I resolve as follows:

CREATE TABLE tenant (
    id INT NOT NULL,
    nome VARCHAR(255) NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE customer (
    id INT  NOT NULL,
    id_tenant INT  NOT NULL,
    nome VARCHAR(255) NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (id_tenant) REFERENCES tenant(id),

    -- pra ter a FK composta, tem que ter chave composta na tabela de origem
    UNIQUE (Id,id_tenant)
);

CREATE TABLE [order]  (
    id INT  NOT NULL,
    id_customer INT  NOT NULL,
    id_tenant INT  NOT NULL,
    nome VARCHAR(255) NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (id_customer, id_tenant) REFERENCES customer (id, id_tenant),
    FOREIGN KEY (id_tenant) REFERENCES tenant(id)
);

How would I do the mapping with my models? How to generate my models with SQL above? With Code First?

public class Tenant
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class Customer
{
    public int Id { get; set; }
    public int TenantId { get; set; }
    public string Name { get; set;}
}
public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public int TenantId { get; set; }

    public float Price { get; set; }
}

Upvotes: 1

Views: 182

Answers (1)

ocuenca
ocuenca

Reputation: 39326

I think what you looking for is a model like this:

public class Tenant
{
    [Key]   
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
}
public class Customer
{
    [Key,Column(Order = 0)]
    public int Id { get; set; }

    [Key,ForeignKey("Tenant"), Column(Order = 1)]
    public int TenantId { get; set; }

    [Required]
    public string Name { get; set; }

    public virtual Tenant Tenant { get; set; }
}
public class Order
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("Customer"), Column(Order = 0)]
    public int CustomerId { get; set; }

    [ForeignKey("Customer"), Column(Order = 1)]
    public int TenantId { get; set; }

    public decimal Price { get; set; }

    public virtual Customer Customer { get; set; }
}

If you want to learn about the annotations I used in this model, you can check this link

Update

Yes, you can have multiples FK properties in an entity as part of the configuration of other relationships, for example, suppose you want to relate the customers with a Group:

 public class Group
 {
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }
    public virtual ICollection<Customer> Customers {get ; set;}
 }

Then, in your Customer class you can have a FK property to the Group Table. Add this:

  public class Customer
  {
     //...
     [ForeignKey("Group")
     public int GroupId { get; set; }

     public virtual Group Group { get; set; }
  } 

Upvotes: 1

Related Questions