简体   繁体   English

避免实体框架中重复项的更简单方法

[英]Easier way of avoiding duplicates in entity framework

Can anyone provide an easier more automatic way of doing this? 任何人都可以提供一种更简单,更自动的方式来执行此操作吗?

I have the following save method for a FilterComboTemplate model. 我为FilterComboTemplate模型具有以下保存方法。 The data has been converted from json to ac# model entity by the webapi. Webapi已将数据从json转换为ac#模型实体。

So I don't create duplicate entries in the DeviceProperty table I have to go through each filter in turn and retrieve the assigned DeviceFilterProperty from the context and override the object in the filter. 因此,我不必在DeviceProperty表中创建重复的条目,而必须依次遍历每个过滤器并从上下文中检索分配的DeviceFilterProperty,并覆盖过滤器中的对象。 See the code below. 请参见下面的代码。

I have all the object Id's if they already exist so it seems like this should be handled automatically but perhaps that's just wishful thinking. 我已经拥有了所有对象ID(如果它们已经存在),因此似乎应该自动处理它,但这也许只是一厢情愿。

public void Save(FilterComboTemplate comboTemplate)
{
    // Set the Device Properties so we don't create dupes
    foreach (var filter in comboTemplate.Filters)
    {
        filter.DeviceProperty = context.DeviceFilterProperties.Find(filter.DeviceFilterProperty.DeviceFilterPropertyId); 
    }

    context.FilterComboTemplates.Add(comboTemplate);
    context.SaveChanges();
}

From here I'm going to have to check whether any of the filters exist too and then manually update them if they are different to what's in the database so as not to keep creating a whole new set after an edit of a FilterComboTemplate. 从这里开始,我将必须检查是否也存在任何过滤器,然后手动更新它们(如果它们与数据库中的过滤器不同),以免在编辑FilterComboTemplate之后不创建全新的集合。

I'm finding myself writing a lot of this type of code. 我发现自己在写很多这类代码。 I've included the other model classes below for a bit of context. 我已经包含下面的其他模型类的一些背景。

public class FilterComboTemplate
{
    public FilterComboTemplate()
    {
        Filters = new Collection<Filter>();
    }

    [Key]
    public int FilterComboTemplateId { get; set; }

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

    [Required]
    public ICollection<Filter> Filters { get; set; }
}

public class Filter
{
    [Key]
    public int FilterId { get; set; }

    [Required]
    public DeviceFilterProperty DeviceFilterProperty { get; set; }

    [Required]
    public bool Exclude { get; set; }

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

public class DeviceFilterProperty
{
    [Key]
    public int DeviceFilterPropertyId { get; set; }

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

It seems that you have some common operations for parameters after it's bound from request. 从请求绑定之后,似乎对参数进行了一些常规操作。

You may consider to write custom parameter bindings to reuse the code. 您可以考虑编写自定义参数绑定以重用代码。 HongMei's blog is a good start point: http://blogs.msdn.com/b/hongmeig1/archive/2012/09/28/how-to-customize-parameter-binding.aspx HongMei的博客是一个很好的起点: http : //blogs.msdn.com/b/hongmeig1/archive/2012/09/28/how-to-customize-parameter-binding.aspx

You may use the code in Scenario 2 to get the formatter binding to deserialize the model from body and perform the operations your want after that. 您可以使用方案2中的代码来获取格式化程序绑定,以从主体反序列化模型,然后执行所需的操作。

See the final step in the blog to specify the parameter type you want customize. 请参阅博客中的最​​后一步,以指定要自定义的参数类型。

Judging from some similar questions on SO, it does not seem something EF does automatically... 从关于SO的一些 类似 问题来看,EF似乎并不会自动执行某些操作...

It's probably not a massive cut on code but you could do something like this, an extension method on DbContext (or on your particular dataContext): 它可能不会大量削减代码,但是您可以执行以下操作,在DbContext(或您的特定dataContext)上使用扩展方法:

public static bool Exists<TEntity>(this MyDataContext context, int id) 
{
    // your code here, something similar to
    return context.Set<TEntity>().Any(x => x.Id == id);
    // or with reflection:
    return context.Set<TEntity>().Any(x => {
        var props = typeof(TEntity).GetProperties();
        var myProp = props.First(y => y.GetCustomAttributes(typeof(Key), true).length > 0)
        var objectId = myProp.GetValue(x)
        return objectId == id;
    });
}

This will check if an object with that key exists in the DbContext. 这将检查DbContext中是否存在具有该键的对象。 Naturally a similar method can be created to actually return that entity as well. 自然地,可以创建类似的方法来实际返回该实体。

There are two "returns" in the code, just use the one you prefer. 代码中有两个“返回”,只需使用您喜欢的一个即可。 The former will force you to have all entities inherit from an "Entity" object with an Id Property (which is not necessarily a bad thing, but I can see the pain in this... you will also need to force the TEntity param: where TEntity : Entity or similar). 前者将迫使您让所有实体都从具有Id属性的“实体”对象继承(这不一定是一件坏事,但是我可以看到这很痛苦……您还需要强制执行TEntity参数: where TEntity : Entity或类似名称)。 Take the "reflection" solution with a pinch of salt, first of all the performance may be a problem, second of all I don't have VS running up now, so I don't even know if it compiles ok, let alone work! 用一点点的“反射”解决方案,首先性能可能是个问题,其次我现在没有VS运行,所以我什至不知道它是否可以编译,更不用说工作了!

Let me know if that works :) 让我知道是否可行:)

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

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