实体框架5使用DBContext模板的DBGenerated标识

时间:2014-03-18 15:27:32

标签: c# entity-framework ado.net repository identity

我对EF很陌生并且尽可能多地阅读教程,但那里有很多相互矛盾的信息。我已经包含了一些代码以防我的方法错误,但实质上我需要弄清楚如何让EF允许DB为标识列生成GUID,目前EF正在写0。

我从一个ADO.NET实体数据模型开始,我在数据库第一种方法中使用它。我在edmx中手动将所有主键设置为StoreGeneratedPattern = Identity。然后我使用了EF5.x DBContext Generator,这创建了我的类。

上下文如下:

public partial class Assets : DbContext
{
    public Assets()
        : base(Common.GetConnString(typeof(Assets)))
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public DbSet<Building> Buildings { get; set; }
    public DbSet<Device> Devices { get; set; }
    public DbSet<Location> Locations { get; set; }
    public DbSet<Manufacturer> Manufacturers { get; set; }
    public DbSet<Model> Models { get; set; }
    public DbSet<OperatingSystem> OperatingSystems { get; set; }
}

实体都非常相似,这是一个看起来像:

public partial class Device : IGuidID
{
    public Guid ID { get; set; }
    public Guid ModelID { get; set; }
    public Nullable<Guid> OperatingSystemID { get; set; }
    public Guid LocationID { get; set; }
    public string DeviceName { get; set; }
    public string Description { get; set; }
    public byte[] BinaryIPAddress { get; set; }

    public string IPAddress
    {
        get
        {
            if (this.BinaryIPAddress == null)
                return null;

            return string.Join(".", this.BinaryIPAddress);
        }
        set
        {
            this.BinaryIPAddress = System.Net.IPAddress.Parse(value).GetAddressBytes();
        }
    }

    public virtual Location Location { get; set; }
    public virtual Model Model { get; set; }
    public virtual OperatingSystem OperatingSystem { get; set; }
}

如果我创建一个新设备并保存它,而不是遵守edmx中定义的设置,我正在编写新设备中定义的GUID,即00000 ...我通过unitofwork和存储库模式保存。

的UnitOfWork:

public class UnitOfWork : UnitOfWorkBase
{
    private Repository<Device> _deviceRepository;

    public Repository<Device> DeviceRepository
    {
        get
        {
            if (_deviceRepository == null)
                _deviceRepository = new Repository<Device>(base.Context);

            return _deviceRepository;
        }
    }

    public UnitOfWork()
        : base(new Model.Assets())
    {
    }
}

public class UnitOfWorkBase : IDisposable
{
    private readonly DbContext _context;

    protected DbContext Context
    {
        get { return _context; }
    }

    public UnitOfWorkBase(DbContext context)
    {
        _context = context;
    }

    public void Save()
    {
        _context.SaveChanges();
    }

    // Additional code Dispose, etc.
}

存储库:

public class Repository<TEntity> : GenericRepository<TEntity>
    where TEntity : class, IGuidID
{
    public Repository(DbContext context)
        : base(context)
    {
    }

    // Additional code here(Contains, etc.)
}

public class GenericRepository<TEntity> where TEntity : class
{
    private readonly DbContext _context;
    private readonly DbSet<TEntity> _dbSet;

    public GenericRepository(DbContext context)
    {
        _context = context;
        _dbSet = context.Set<TEntity>();
    }

    public virtual IEnumerable<TEntity> All()
    {
        return _dbSet.AsEnumerable();
    }

    public virtual void Delete(TEntity entityToDelete)
    {
        if (_context.Entry(entityToDelete).State == EntityState.Detached)
            _dbSet.Attach(entityToDelete);

        _dbSet.Remove(entityToDelete);
    }

    public virtual void Insert(TEntity entity)
    {
        _dbSet.Add(entity);
    }

    public virtual void Update(TEntity entityToUpdate)
    {
        if (_context.Entry(entityToUpdate).State == EntityState.Detached)
            _dbSet.Attach(entityToUpdate);

        _context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}

老实说,这个行为并不让我感到惊讶,如果我附加一个带有0000 ... ID的设备我希望它会这样插入,但我不确定如何解决或出现问题。我的所有ID都应该可以为空,即使它们不在数据库中吗?我需要做一些映射吗?当我还在使用Linq to SQL时,这种事情就“起作用了”。

谢谢 - 德里克

2 个答案:

答案 0 :(得分:1)

我认为您需要将以下属性应用于GUID属性

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ID { get; set; }

您需要将以下命名空间添加到您的类

using System.ComponentModel.DataAnnotations.Schema;

答案 1 :(得分:1)

我找到了解决方案here。基本上通过VisualStudio中的属性编辑edmx文件只会改变ConceptualModels。我也需要修改StorageModels,我不知道是否有其他方法,但手动修改XML对我有效。我必须将StoreGeneratedPattern =“Identity”添加到主键属性。

<EntityType Name="Devices">
    <Key>
        <PropertyRef Name="DeviceID" />
    </Key>
    <Property Name="DeviceID" Type="uniqueidentifier" Nullable="false" StoreGeneratedPattern="Identity" />
    <!--Additional Properties-->