简体   繁体   English

实体框架中的类型化ID

[英]Typed Ids in entity framework

On the client side (WPF or Silverlight for example), I usually model entity ids by creating a id class for each entity: 在客户端(例如WPF或Silverlight),我通常通过为每个实体创建一个id类来对实体id进行建模:

class CarId { public readonly int Id; ... } // or string or Guid etc

so that I can have strongly typed ids and I won't have to pass around ints (or string or guid) without type information: 这样我就可以使用强类型的ID,而不必在没有类型信息的情况下传递整数(或字符串或guid):

class Car { public CarId Id { get; private set; } ... }

(A similar reusable way is to create a generic class Id and have Id). (一种类似的可重用方法是创建一个通用类ID并具有ID)。

Being new to entity framework and not having done a lot of back-end work, I wonder, is it possible to have entity framework map typed ids like those to primary key (integer/string/guid) table columns in the db? 我想知道,作为实体框架的新手,并且没有做很多后端工作,是否有可能使db的实体框架映射类型的ID类似于主键(整数/字符串/ guid)表列的ID? Initially I'd like to be able to use code-first. 最初,我希望能够先使用代码。

实体框架中的键始终为原始类型-复合键也是如此。

I haven't toyed with this enough yet, but using the technique shown here , you can create strongly typed IDs which are more convenient to use. 我还没有足够的知识,但是使用此处显示的技术 ,您可以创建更方便使用的强类型ID。

abstract class BaseEntity
{
}

abstract class BaseEntityWithID<TEntity> : IPrimaryKey<Guid, TEntity>
{
    public ID<Guid, TEntity> ID
    {
        get;
        set;
    }
}

class TestOne : BaseEntityWithID<TestOne>
{
    public string TestString { get; set; }
}

class TestTwo : BaseEntityWithID<TestTwo>
{
    public string TestString { get; set; }
}

interface IPrimaryKey<T, TEntity>
{
    ID<T, TEntity> ID { get; set; }
}

struct ID<T, TEntity> : IEquatable<ID<T, TEntity>>
{
    readonly T _id;

    public ID(T id)
    {
        _id = id;
    }

    public T Value { get { return _id; } }

    public bool Equals(ID<T, TEntity> other)
    {
        if (_id == null || other._id == null)
            return object.Equals(_id, other._id);

        return _id.Equals(other._id);
    }

    public static implicit operator T(ID<T, TEntity> id)
    {
        return id.Value;
    }

    public static implicit operator ID<T, TEntity>(T id)
    {
        return new ID<T, TEntity>(id);
    }

    //I believe this class also needs to override GetHashCode() and Equals()
}

class Program
{
    static void Main(string[] args)
    {
        var testOneStore = new Dictionary<ID<Guid, TestOne>, TestOne>();
        var testTwoStore = new Dictionary<ID<Guid, TestTwo>, TestTwo>();

        Func<TestOne, TestOne> addTestOne = (entity) =>
        {
            if (entity.ID == Guid.Empty)
            {
                entity.ID = Guid.NewGuid();
            }

            testOneStore.Add(entity.ID, entity);

            return entity;
        };

        Func<TestTwo, TestTwo> addTestTwo = (entity) =>
        {
            if (entity.ID == Guid.Empty)
            {
                entity.ID = Guid.NewGuid();
            }

            testTwoStore.Add(entity.ID, entity);

            return entity;
        };

        var id1 = addTestOne(new TestOne { TestString = "hi" }).ID;
        var id2 = addTestTwo(new TestTwo { TestString = "hello" }).ID;

        Console.WriteLine(testOneStore[id1].TestString); //this line works
        Console.WriteLine(testOneStore[id2].TestString); //this line gives a compile-time error

        Console.ReadKey(true);
    }
}

I haven't used this with Entity Framework yet, but I suspect the BaseEntityWithID<> type will need to mark the ID property as not included in the model, and use a property marked internal to provide value storage. 我尚未将其用于Entity Framework,但我怀疑BaseEntityWithID<>类型将需要将ID属性标记为未包含在模型中,并使用标记为internal的属性来提供值存储。 It would be nice if there's a way to get EF to just use the ID<> type, but I haven't looked into this at all. 如果有一种方法可以让EF只使用ID<>类型,那就太好了,但是我完全没有研究过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM