Как проверить, существует ли запись в отдельной таблице SQL Server, и изменить, какая функция связана в зависимости от того, существует она или нет - PullRequest
0 голосов
/ 20 марта 2020

Прежде чем я начну, я относительно новичок в программировании и должен был начать свою первую младшую роль в будущем, поэтому мой текущий уровень квалификации довольно базовый c.

Я создаю персональное C# ASP. NET MVC веб-приложение для отслеживания музыкальных c событий, к которым пользователи go обращаются, и исполнителей, которые играют на этих событиях, а также артистов, которых видит пользователь. Все это делается пользователем, вручную добавляющим события из индексированного представления всех событий в базе данных (SQL Сервер), что показано на изображении, связанном ниже.

https://i.stack.imgur.com/HOUGG.png

Действие контроллера:

        public ActionResult GetEvents()
        {
            return View(_trackerService.GetEvents());
        }

Разметка для вида:

@model IEnumerable<Tracker.Data.tbl_events>

@{
    ViewBag.Title = "GetEvents";
}

<h2>GetEvents</h2>

<p>
    @Html.ActionLink("Create New", "CreateEvent")
</p>
<table class="table">

    <tr><h2>Upcoming Events</h2>
        <th>
            @Html.DisplayNameFor(model => model.Event_ID)
        </th><th>
            @Html.DisplayNameFor(model => model.Event_Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Event_Date)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Event_Location)
        </th>
    </tr>

    @foreach (var item in Model.Where( x => x.Event_Date >= System.DateTime.Now).OrderBy(x => x.Event_Date))
    {

<tr>
    <td>
        @Html.DisplayFor(modelItem => item.Event_ID)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Event_Name)
    </td>
    <td>
        @Convert.ToString(string.Format("{0:dd/MM/yyyy}", item.Event_Date)) @*Converts the DateTime data type that ASP.NET uses by default into a string with the format of Date Only (https://stackoverflow.com/a/34990313/12764653)*@
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Event_Location)
    </td>
    <td>
        @*@Html.ActionLink("Edit", "Edit", new { id = item.Event_ID }) | *@
        @Html.ActionLink("Details", "GetEventDetails", new { Event_ID = item.Event_ID }) |
        @Html.ActionLink("Lineup", "../Event/GetLineup", new { Event_ID = item.Event_ID, Event_Name = item.Event_Name }) |
        @if ((System.Web.HttpContext.Current.User != null) && System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
        {@*Checks to see if there is a current user*@
        @Html.ActionLink("Add to my Events", "../Event/AddToUser", new { User_ID = Convert.ToString(System.Web.HttpContext.Current.User.Identity.GetUserId()).GetHashCode(), Event_ID = item.Event_ID })}
    @*@Html.ActionLink("Delete", "Delete", new { id = item.Event_ID })*@
    </td>
</tr>
    }
</table>

Один раз пользователь добавляет событие в свой профиль, он создает запись в базе данных с полями (связаны ниже):

https://i.stack.imgur.com/YQqHT.png

Метод контроллера для Функция «Добавить в мои события» функция:

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)] 
public ActionResult AddToUser(tbl_eventhistory _event)
{
        try
        {
            _trackerService.AddToUser(_event);
            return RedirectToAction("GetEvents");
        }
        catch
        {
            return View();
        }
}

Я понимаю, что при нынешнем состоянии это, скорее всего, должно быть сделано либо в контроллере, либо в представлении, и это будет сделано, чтобы проверить 'tbl_eventhistory', чтобы увидеть, существует ли запись с текущими пользователями User_ID и конкретным c Event_ID, однако я не уверен, как на самом деле это сделать, поэтому любая помощь будет принята с благодарностью.

РЕДАКТИРОВАТЬ: Показанная таблица является индексированным представлением 'tbl_events'. Когда пользователь добавляет событие в свой профиль из этого представления, он создает запись в другой таблице с именем «tbl_eventhistory», используя параметры для этого указанного события c, которое связано через внешний ключ в Event_ID (PK tbl_event) , Когда пользователь добавляет событие в tbl_eventhistory, я хочу удалить ссылку «Добавить к пользователю» из представления только для этого указанного c события.

Ответы [ 2 ]

0 голосов
/ 20 марта 2020

Удалось наконец-то найти решение. Пожалуйста, прости меня, если терминология неверна.

У меня уже была функция для возврата индексированного представления определенных c пользовательских событий (код класса DAO ниже)

        public IList<tbl_eventhistory> GetUserEvents(string User_ID)
        {
            IQueryable<tbl_eventhistory> _eventHistory;
            _eventHistory = from tbl_eventhistory in _context.tbl_eventhistory where tbl_eventhistory.User_ID == User_ID select tbl_eventhistory;
            return _eventHistory.ToList<tbl_eventhistory>();
        }

Думая, как чтобы использовать эти данные в представлении с другой связанной моделью, я подумал об использовании ViewBag и натолкнулся на следующее: «Как проверить, содержит ли List в ViewBag строку» . Из этого ответа я изменил свою функцию 'GetEvents' следующим образом:

public ActionResult GetEvents()
        {
            List<string> UsersEvents = new List<string>();
            foreach (var item in _trackerService.GetUserEvents(User_ID))
            {
                UsersEvents.Add(item.Event_ID.ToString());
            }
            ViewBag.MyEvents = _trackerService.GetUserEvents(User_ID);
            ViewBag.MyEvents = UsersEvents;
            return View(_trackerService.GetEvents());
        }

Если мое понимание верно, это создает список, который заполняется путем вызова действия 'GetUserEvents' и проходит по каждой записи в результат. Перемещение этого списка в ViewBag позволяет затем изменить ActionLink'ы GetEvents, чтобы включить в существующий оператор дополнительный оператор IF, проверяющий, вошел ли пользователь в систему:

@if ((System.Web.HttpContext.Current.User != null) && System.Web.HttpContext.Current.User.Identity.IsAuthenticated)

if (((IList<string>)ViewBag.MyEvents).Contains(item.Event_ID.ToString())){ 
       <p>TEST</p> }
else{
       @Html.ActionLink("Add to my Events", "../Event/AddToUser", new { User_ID = Convert.ToString(System.Web.HttpContext.Current.User.Identity.GetUserId()).GetHashCode(), Event_ID = item.Event_ID })}
            }

, что привело к тому, что "Test" был отображается вместо ссылки «Добавить к пользователю», где это уместно (показано ниже, а последнее событие отсутствует в «tbl_eventhistory»):

http://icecream.me/b459c9d17854b081a0804692f67c3aa3

Я понимаю, что это, пожалуй, самый далекий из самых эффективных способов сделать это, но я просто рад, что теперь это работает после долгого времени, пытаясь выяснить это.

0 голосов
/ 20 марта 2020

У вас уже есть ссылка Delete в вашем представлении Razor - это, кажется, достаточно хорошо:

@Html.ActionLink("Delete", "../Event/DeleteEvent", new { id = item.Event_ID })

И тогда ваш EventController будет выглядеть что-то анологичное в следующих строках:

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)] 
public ActionResult DeleteEvent(int id)
{
        try
        {
            _trackerService.DeleteForUser(HttpContext.Current.User.Identity.GetUserId(), _event); // this is where you verify whether currently logged in user has access and delete their associated event. 
            //depending on your data access framework of choice you should aim to fire a query like so: 
            //DELETE FROM table WHERE User_Id = :user_id AND Event_Id = :id 
            //that would cover you for users deleing only items belonging to them
            return RedirectToAction("GetEvents");
        }
        catch
        {
            return View();
        }
}

Теперь, чтобы указать на две проблемы безопасности с вашим кодом AddEvent:

@Html.ActionLink("Add to my Events", "../Event/AddToUser", new { User_ID = Convert.ToString(System.Web.HttpContext.Current.User.Identity.GetUserId()).GetHashCode(), Event_ID = item.Event_ID })}
  1. GetHashCode() - это не то, что вы думаете: использовать его в качестве идентификатора небезопасные, потому что коллизии при реализации по умолчанию весьма вероятны
  2. . Нет необходимости даже передавать идентификатор пользователя обратно из клиента: ваши контроллеры имеют доступ к объекту HttpContext, поэтому вы можете просто захватить этот User_ID на на стороне сервера

и попытаться ответить на ваши вопросы в заголовке:

Как проверить, существует ли запись в отдельной SQL таблице сервера,

Не думаю, что вам это нужно для удаления событий - посмотрите комментарии в приведенном выше коде

и измените, какая функция связана, в зависимости от того, существует она или нет

Я не уверен, что получу эта часть. Я чувствую, что вы, возможно, сможете ответить на оба эти вопроса самостоятельно после просмотра этого другого SO вопроса на SQL JOIN . В противном случае мне (и сообществу здесь) потребуется более подробная информация о вашем фактическом сценарии использования и цели

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...