泛型和实体框架:如何根据列值返回不同的类型

发布于 2024-10-13 07:46:00 字数 993 浏览 3 评论 0原文

我们有一个人员表,其中存储不同类型的人员(买方、卖方、代理商等)。我们的 ORM 是实体框架 CodeFirst (CTP5)。我们使用存储库模式来实现良好的 TDD 和模拟。在 PersonRepository 中,我想返回一个特定类型,这样我就可以做这样的事情:

Agent a = repository.Get<Agent>(5005);  // Where 5005 is just an example Id for the person
a.SomeAgentProperty = someValue;
Buyer b = repository.Get<Buyer>(253);   // Again, a simple PersonId.
b.SomeBuyerProperty = someOtherValue;

这个想法是,当我从存储库中获取它时,我知道我会得到什么样的人。是的,我可以创建 X 个不同的 Get 方法,称为 GetBuyer(int PersonId)、GetSeller(int PersonId) 等。但这有一种代码味道。

通用函数看起来如何?

到目前为止,这是我的存储库界面:

public interface IPersonRepository
{
    Person Get(int PersonId);   // To get a generic person
    T Get<T>(int PersonId);     // To get a specific type of person (buyer, agent, etc.)
    void Save(Person person);
    void Delete(int p);
}

以及我的具体实现:

    public T Get<T>(int PersonId)
    {
        //Here's my question: What goes here?
    }

We have a Persons table which stores different types of persons (Buyer, Seller, Agent, etc). Our ORM is Entity Framework CodeFirst (CTP5). We're using the repository pattern for good TDD and mocking. In the PersonRepository I want to return a specific type so I can do things like this:

Agent a = repository.Get<Agent>(5005);  // Where 5005 is just an example Id for the person
a.SomeAgentProperty = someValue;
Buyer b = repository.Get<Buyer>(253);   // Again, a simple PersonId.
b.SomeBuyerProperty = someOtherValue;

The idea is that I know what kind of person I'm getting when I get it from the repository. And, yes, I could just create X different Get methods called GetBuyer(int PersonId), GetSeller(int PersonId) and so on. But that has a code smell.

How would the generic function look?

Here is my repository interface so far:

public interface IPersonRepository
{
    Person Get(int PersonId);   // To get a generic person
    T Get<T>(int PersonId);     // To get a specific type of person (buyer, agent, etc.)
    void Save(Person person);
    void Delete(int p);
}

And my concrete implementation:

    public T Get<T>(int PersonId)
    {
        //Here's my question: What goes here?
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽清梦 2024-10-20 07:46:00

使用 OfType() 方法,如果您使用 TPT,这将导致 EF 对指定的 T 执行 INNER JOIN,或者如果您使用 TPH,则执行基于鉴别器的过滤器。

public TPerson Get<TPerson>(int PersonId) where TPerson : Person
{
    return ctx.People
              .OfType<TPerson>()
              .SingleOrDefault(x => x.PersonId == PersonId);
}

这将像你想要的那样工作:

Agent a = repository.Get<Agent>(5005);

Use the OfType<T>() method, which will result in EF doing an INNER JOIN to the specified T if your using TPT, or a filter based on the discriminator if your using TPH.

public TPerson Get<TPerson>(int PersonId) where TPerson : Person
{
    return ctx.People
              .OfType<TPerson>()
              .SingleOrDefault(x => x.PersonId == PersonId);
}

And that will work just like you wanted:

Agent a = repository.Get<Agent>(5005);
香草可樂 2024-10-20 07:46:00

我建议使用类似的方法:

public T Get<T>(int PersonId) where T: new()
{
    return new T(PersonId);
}

并在构造函数中加载数据或为每种类型的实体实现某种 Load 方法,例如:

interface IEntity
{
    void Load(int Id);
}

class CBuyer: IEntity
{
    public Load(int Id) { ... }
}

public T Get<T>(int PersonId) where T: IEntity, new()
{
    T ent = new T();
    ent.Load(PersonId);
    return ent;
}    

I would suggest to use something like:

public T Get<T>(int PersonId) where T: new()
{
    return new T(PersonId);
}

and load data in the constructor or implement some kind of Load method for each type of your entity, like:

interface IEntity
{
    void Load(int Id);
}

class CBuyer: IEntity
{
    public Load(int Id) { ... }
}

public T Get<T>(int PersonId) where T: IEntity, new()
{
    T ent = new T();
    ent.Load(PersonId);
    return ent;
}    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文