在实体框架代码的第一个方法中,两个字段的组合必须是唯一的。怎么会 [英] combination of two field must be unique in Entity Framework code first approach. how it would?

查看:84
本文介绍了在实体框架代码的第一个方法中,两个字段的组合必须是唯一的。怎么会的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类联系人和组



组合 FirstName LastName 必须是唯一的,可以为单个联系人添加多个地址。如何在实体框架代码第一种方法中做到这一点?

  public class Contacts 
{
[Key ]
public int ContactID {get;组; }
[ForeignKey(Group)]
public int GroupID {get;组; }
[必需]
public string FirstName {get;组; }
[必需]
public string LastName {get;组; }
[必需]
public string Address {get;组; }
[必需]
public string Number {get;组; }
[必需]
[EmailAddress]
public string EmailId {get;组; }
[DataType(DataType.Date)]
public DateTime CreateDate {get;组; }
public DateTime? ModifiedDate {get;组; }

public virtual Groups Group {get;组;


public class Groups
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int GroupID {get ;组; }
[必需]
public string GroupName {get;组; }
[必需]
public string GroupDiscription {get;组; }
public DateTime CreateDate {get;组; }
public DateTime ModifiedDate {get;组; }
}


解决方案

必须去数据库才能验证。在实体框架代码中首先,这意味着使用DbContext。请参阅使用ValidateEntity在上下文中实现验证,以了解如何在实体框架中验证。



您应该覆盖上下文类中的ValidateEntity方法:

 
$ b {
//数据注释基础验证,IValidatableObject $ b(

$ b {
$ b var result = base.ValidateEntity(entityEntry,items);

//您可以选择在自定义验证之前保释
// if(result.IsValid)
//返回结果;

CustomValidate(result);
返回结果;
}

private void CustomValidate(DbEntityValidationResult result)
{
ValidateContacts(result);
ValidateOrganisation(result);
}

private void ValidateContacts(DbEntityValidationResult result)
{
var c = result.Entry.Entity as Contact;
if(c == null)
return;

if(Contacts.Any(a => a.FirstName == c.FirstName
&& a.LastName == c.LastName
&& a.ID!= c.ID))
result.ValidationErrors.Add(
new DbValidationError(Name,
Name already exists));
}

private void ValidateOrganisation(DbEntityValidationResult result)
{
var organization = result.Entry.Entity as Organization;
if(organization == null)
return;

if(Organisations.Any(o => o.Name == organisation.Name
& o.ID!= organisation.ID))
结果。 ValidationErrors.Add(
new DbValidationError(Name,
Name already exists));
}

当调用的SaveChanges 。如果有任何错误,将抛出一个 DbEntityValidationException



有关结构化验证的更多信息这里



对于腰带和大括号方法,我还向数据库添加唯一索引我的天然钥匙 - 在迁移。因此,因为不通过Entity Framework插入到数据库,因此阻止了无效数据:

  public partial class Adduniqueindexes:DbMigration 
{
public override void Up()
{
//如果列为空,则必须使用Sql:
Sql(@CREATE UNIQUE INDEX IX_UPRN ON Properties( UPRN,OrganisationID)
WHERE UPRN不为空));
CreateIndex(dbo.Organisations,
Name,
unique:true,
name:IX_NaturalKey);
CreateIndex(dbo.Contacts,
new string [] {FirstName,LastName},
unique:true,
name:IX_NaturalKey);
}

public override void Down()
{
DropIndex(dbo.Properties,IX_UPRN);
DropIndex(dbo.Organisations,IX_NaturalKey);
DropIndex(dbo.Contacts,IX_NaturalKey);
}
}

有关索引的更多信息
从EF6.1起可以通过添加一个数据属性来指示在一个字段上创建索引:

  [Index(IX_NaturalKey ,IsUnique = true)] 
[必需] //如果该字段为空,那么您必须在迁移
//中使用sql创建索引,所以我只会期望IsUnique = true必需字段
[StringLength(256)] //索引在Sql Server中必须小于900字节,
// so nvarchar(max)不会执行
public string Name {get;组; }


I have two class contacts and groups

Combination of FirstName and LastName must be unique and can add multiple addresses for a single contact. How I can done this in entity framework code first approach?

public class Contacts
{
    [Key]
    public int ContactID { get; set; }
    [ForeignKey("Group")]
    public int GroupID { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    [Required]
    public string Address { get; set; }
    [Required]
    public string Number { get; set; }
    [Required]
    [EmailAddress]
    public string EmailId { get; set; }
    [DataType(DataType.Date)]
    public DateTime CreateDate { get; set; }
    public DateTime? ModifiedDate { get; set; }

    public virtual Groups Group { get; set; }
}

public class Groups
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int GroupID { get; set; }
    [Required]
    public string GroupName { get; set; }
    [Required]
    public string GroupDiscription { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime ModifiedDate { get; set; }
}

解决方案

Checking for duplicates means you have to go to the database to validate. In Entity Framework Code First, that means using the DbContext. See Implementing Validation in the Context with ValidateEntity for a great explanation of how to validate in Entity Framework.

You should override the ValidateEntity method in your context class:

    protected override DbEntityValidationResult ValidateEntity(
                                        DbEntityEntry entityEntry, 
                                        IDictionary<object, object> items)
    {
        //base validation for Data Annotations, IValidatableObject
        var result = base.ValidateEntity(entityEntry, items);

        //You can choose to bail out before custom validation
        //if (result.IsValid)
        //    return result;

        CustomValidate(result);
        return result;
    }

    private void CustomValidate(DbEntityValidationResult result)
    {
        ValidateContacts(result);
        ValidateOrganisation(result);
    }

private void ValidateContacts(DbEntityValidationResult result)
{
    var c = result.Entry.Entity as Contact;
    if (c== null)
        return;

    if (Contacts.Any(a => a.FirstName == c.FirstName 
                          && a.LastName == c.LastName 
                          && a.ID != c.ID))
        result.ValidationErrors.Add(
                          new DbValidationError("Name", 
                                "Name already exists"));
}

private void ValidateOrganisation(DbEntityValidationResult result)
{
    var organisation = result.Entry.Entity as Organisation;
    if (organisation == null)
        return;

    if (Organisations.Any(o => o.Name == organisation.Name 
                               && o.ID != organisation.ID))
        result.ValidationErrors.Add(
                              new DbValidationError("Name", 
                                    "Name already exists"));
}

This validation is triggered when there is a call to SaveChanges. If there are any errors, a DbEntityValidationException is thrown.

More about structuring validation here

For a "belt and braces" approach I also add unique indexes to the database on my natural keys - in a migration. Thus preventing invalid data because of inserts to the database that do not go via Entity Framework :

public partial class Adduniqueindexes : DbMigration
{
    public override void Up()
    {
        //You have to use Sql if the column is nullable:
        Sql(@"CREATE UNIQUE INDEX IX_UPRN ON Properties(UPRN, OrganisationID) 
            WHERE UPRN IS NOT NULL"));
        CreateIndex("dbo.Organisations", 
                    "Name", 
                     unique: true, 
                     name: "IX_NaturalKey");
        CreateIndex("dbo.Contacts", 
                    new string[] { "FirstName", "LastName" }, 
                    unique: true, 
                    name: "IX_NaturalKey");
    }

    public override void Down()
    {
        DropIndex("dbo.Properties", "IX_UPRN");
        DropIndex("dbo.Organisations", "IX_NaturalKey");
        DropIndex("dbo.Contacts", "IX_NaturalKey");
    }
}

More about indexes here

Additional note From EF6.1 onwards it is possible to indicate that an index should be created on a field by adding a data attribute:

[Index("IX_NaturalKey", IsUnique = true)]
[Required] //If the field is nullable then you have to create the index in the migration
           //using sql, so I'd only expect IsUnique = true on a Required field
[StringLength(256)] //indexes must be less than 900 bytes in Sql Server,
                    //so nvarchar(max) will not do
public string Name{ get; set; }

这篇关于在实体框架代码的第一个方法中,两个字段的组合必须是唯一的。怎么会的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆