I want to perform some simple queries for these below models using EF Core code first.
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
public class FirstTag
{
public int Id { get; set; }
public string tagName { get; set; }
public ICollection<Post> Post { get; set; }
}
SecondTag
model
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
Id | tagName
1 firstTag1
2 firstTag2
SecondTag
table
Id | tagName
1 secondTag1
2 secondTag2
And this is my JSON data for adding new post
{
"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
. 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?
CodePudding user response:
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.
Your class Post
does not contain the definition for SecondTag
but I'll assume it's the same as FirstTag
. You're also missing Id
in your JSON example.
Ignoring those inconsistencies, you're first defining 2 variables in your CreatePost
: tag1
and tag2
. Since postParam
will not have a filled tag, both of these variables will initialize as null
. As such, it's logical that both if statements will validate as 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
. If you NEVER want tag2 to be filled with a tag of tag1, do something like this:
tag2 = _context.SecondTags.Where(x =>
string.IsNullOrEmpty(postParam.Post.SecondTag.tagName) || (x.tagName == postParam.Post.SecondTag.tagName && postParam.Post.FirstTag.tagName != x.tagName)
.FirstOrDefault());
CodePudding user response:
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. 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.)
CodePudding user response:
You can check for duplicate records as follows
var isDuplicate = _context.FirstTags.Any(x =>x.tagName == postParam.Post.FirstTag.tagName)
if(isDuplicate){
//Do something
}