简体   繁体   English

LINQ C# 现有元素的 FirstOrDefault() 查询返回 null

[英]LINQ C# FirstOrDefault() query return null for the existing element

I want to perform some simple queries for these below models using EF Core code first.我想首先使用 EF Core 代码对以下这些模型执行一些简单的查询。

Post model Post model

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public int FirstTagId { get; set; }
    public FirstTag FirstTag { get; set; }
    public int SecondTagId { get; set; }
    public SecondTag SecondTag { get; set; }
}

FirstTag model FirstTag

public class FirstTag
{
    public int Id { get; set; }
    public string tagName { get; set; }
    public ICollection<Post> Post { get; set; }
}

SecondTag model SecondTag

public class SecondTag
{
    public int Id { get; set; }
    public string tagName { get; set; }
    public ICollection<Post> Post { get; set; }
}

My intention is that when I create a new post.我的意图是当我创建一个新帖子时。 I want to check that does the tag will be inserted into the new post exists or not using the below check operation我想使用以下检查操作检查标签是否会插入到新帖子中是否存在

[HttpPost]
public async Task<ActionResult<Post>> CreatePost([FromBody] NewPostParam postParam)
{
    // to prevent inserting duplicate first tag
    var tag1 = _context.FirstTags.Where(x =>
        (string.IsNullOrEmpty(postParam.Post.FirstTag.tagName) || x.tagName == postParam.Post.FirstTag.tagName))
        .FirstOrDefault();
    // to prevent inserting duplicate second tag 
    var tag2 = _context.SecondTags.Where(x =>
        (string.IsNullOrEmpty(postParam.Post.SecondTag.tagName) || x.tagName == postParam.Post.SecondTag.tagName))
        .FirstOrDefault();

    if (tag1 == null)
    {
        tag1 = new FirstTag
        {
            tagName = "tag1 test",
            tagDescription = "tag1 test des!!"
        };
        _context.FirstTags.Add(tag1);
    }
    if (tag2 == null)
    {
        tag2 = new SecondTag
        {
            tagName = "tag2 test",
            tagDescription = "tag2 test des!"
        };
        _context.SecondTags.Add(tag2);
    }
     var newPost = new Post
     {
        Title = postParam.Post.Title,
        Description = postParam.Post.Description,
        FirstTag = tag1 != null ? tag1 : postParam.Post.FirstTag,
        SecondTag = tag2 != null ? tag2 : postParam.Post.SecondTag,
     };

    _context.Posts.Add(newPost);
    // remain code ...
}

This is the currently existing tags database这是当前存在的标签数据库

FirstTag table FirstTag

Id  |  tagName
1     firstTag1
2     firstTag2

SecondTag table SecondTag

Id  |  tagName 
1      secondTag1
2      secondTag2

And this is my JSON data for adding new post这是我用于添加新帖子的 JSON 数据

{
    "post": {
        "title": "post2 test titlte",
        "description": "post2 test description!",
         "firstTag": {
            "tagName": "firstTag1",
            "tagDescription": "firstTag des!!"
        },
        "secondTag": {
            "tagName": "secondTag2",
            "tagDescription": "secondTag des!!"
        }
    }
}

I've tried several times to add the same name for FirstTag and SecondTag .我曾多次尝试为FirstTagSecondTag添加相同的名称。 But the new data is just created and the check operation I performed above maybe did nothing to prevent that.但是新数据刚刚创建,我上面执行的检查操作可能没有阻止它。 What do I do to prevent duplicate data from being inserted?如何防止插入重复数据?

Unless you did not post something from your data model, FirstTag and SecondTag should be the same Model, or at the very least inherit from the same base model.除非你没有从你的数据 model 中发布一些东西, FirstTagSecondTag应该是相同的 Model,或者至少从相同的基础 model 继承。

Your class Post does not contain the definition for SecondTag but I'll assume it's the same as FirstTag .您的 class Post不包含SecondTag的定义,但我假设它与FirstTag相同。 You're also missing Id in your JSON example.您的 JSON 示例中也缺少Id

Ignoring those inconsistencies, you're first defining 2 variables in your CreatePost : tag1 and tag2 .忽略这些不一致,您首先在CreatePost中定义 2 个变量: tag1tag2 Since postParam will not have a filled tag, both of these variables will initialize as null .由于postParam没有填充标签,因此这两个变量都将初始化为null As such, it's logical that both if statements will validate as true因此,两个 if 语句都将验证为true是合乎逻辑的

So, what you want to do is more along the lines of:因此,您想要做的更多是:

[HttpPost]
public async Task<ActionResult<Post>> CreatePost([FromBody] NewPostParam postParam)
{
    // to prevent inserting duplicate first tag
    var tag1 = _context.FirstTags.Where(x =>
        (string.IsNullOrEmpty(postParam.Post.FirstTag.tagName) || x.tagName == postParam.Post.FirstTag.tagName))
        .FirstOrDefault();
SecondTag tag2 = null;

if (tag1 == null)
{
    tag1 = new FirstTag
    {
        tagName = "tag1 test",
        tagDescription = "tag1 test des!!"
    };
    _context.FirstTags.Add(tag1);
}
else
{
   tag2 = _context.SecondTags.Where(x =>
        (string.IsNullOrEmpty(postParam.Post.SecondTag.tagName) || x.tagName == postParam.Post.SecondTag.tagName))
        .FirstOrDefault();

   if (tag2 == null)
   {       
       tag2 = new SecondTag
       {
           tagName = "tag2 test",
           tagDescription = "tag2 test des!"
       };
       _context.SecondTags.Add(tag2);
   }
}
 var newPost = new Post
 {
    Title = postParam.Post.Title,
    Description = postParam.Post.Description,
    FirstTag = tag1 != null ? tag1 : postParam.Post.FirstTag,
    SecondTag = tag2 != null ? tag2 : postParam.Post.SecondTag,
 };

_context.Posts.Add(newPost);
// remain code ...
}

Secondly, you're not checking whether tag1 already has a value like tag2 .其次,您没有检查tag1是否已经具有类似tag2的值。 If you NEVER want tag2 to be filled with a tag of tag1, do something like this:如果您从不希望 tag2 被 tag1 的标签填充,请执行以下操作:

tag2 = _context.SecondTags.FirstOrDefault(x =>
            string.IsNullOrEmpty(postParam.Post.SecondTag.tagName) ||  (x.tagName == postParam.Post.SecondTag.tagName && postParam.Post.FirstTag.tagName != x.tagName));

Ignoring some questionable aspects of your design, try this:忽略设计中一些有问题的方面,试试这个:

if(!string.IsNullOrEmpty(postParam.Post.FirstTag.tagName))
{
    if(!_context.FirstTags.Any(t => t.tagName.Trim().ToLower() == postParam.Post.FirstTag.tagName.Trim().ToLower()))
    {
        var tag1 = new FirstTag
        {
            tagName = "tag1 test",
            tagDescription = "tag1 test des!!"
        };
        _context.FirstTags.Add(tag1);
    }
}

if (!string.IsNullOrEmpty(postParam.Post.SecondTag.tagName))
{
    if (!_context.FirstTags.Any(t => t.tagName.Trim().ToLower() == postParam.Post.SecondTag.tagName.Trim().ToLower()))
    {
        var tag2 = new FirstTag
        {
            tagName = "tag1 test",
            tagDescription = "tag1 test des!!"
        };
        _context.SecondTags.Add(tag2);
    }
}

As you can see, I separated validation of the model value from the query.如您所见,我将 model 值的验证与查询分开。 I personally dislike convoluted one-liners that make things hard to understand.我个人不喜欢令人费解的单行代码,这会使事情变得难以理解。

The code checks if there is match, taking into account padding and casing (since I don't know much about your backend).该代码检查是否存在匹配,同时考虑填充和大小写(因为我对您的后端了解不多)。

Back to the questionable design.回到有问题的设计。 Notice how the code is suspiciously repetitive?请注意代码是如何可疑地重复的? (Hint: It has to do with the fact that a tag is a tag, regardless of its order or how many there are.) (提示:这与标签就是标签这一事实有关,无论其顺序或数量如何。)

You can check for duplicate records as follows您可以检查重复记录如下

var isDuplicate = _context.FirstTags.Any(x =>x.tagName == postParam.Post.FirstTag.tagName)
if(isDuplicate){
  //Do something
}

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

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