implementation/add-data-classes #1

Merged
VsevolodKozlov123 merged 10 commits from implementation/add-data-classes into master 2024-12-12 16:11:43 +00:00
63 changed files with 3617 additions and 16 deletions

View File

@ -0,0 +1,45 @@
using domain.Service;
using domain.UseCase;
using domain.Request;
using domain.Service;
using Microsoft.AspNetCore.Mvc;
using Presence.Api.Response;
namespace Presence.Api.Controllers
{
[ApiController]
[Route("[controller]/api")]
public class GroupController: ControllerBase
{
private readonly IGroupUseCase _groupService;
public GroupController(IGroupUseCase groupService)
{
_groupService = groupService;
}
[HttpGet("/group")]
public async Task<ActionResult<GroupResponse>> GetAllGroups()
{
var result = _groupService
.GetGroupsWithStudents();
var response = result
.Select(group => new GroupResponse {
Id = group.Id,
Name = group.Name,
Users = group.Users.Select(user => new UserResponse {
Guid = user.Guid,
Name = user.Name
}).ToList(),
}).ToList();
return Ok(new GroupResponse());
}
[HttpPost("/admin/{groupId}/students")]
public void AddGroup(int groupId, [FromBody] AddGroupRequest addGroupRequest)
{
Console.WriteLine(groupId);
_groupService.AddGroup(addGroupRequest);
}
}
}

View File

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
namespace Presence.Api.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View File

@ -0,0 +1,20 @@
using data;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Presence.Api.Controllers;
namespace Presence.Api.Extensions
{
public static class ServiceCollectionsExtension
{
public static void AddCommomService(this IServiceCollection services)
{
services
.AddDbContext<RemoteDatabaseContext>()
.AddScoped<IGroupRepository, SQLGroupRepository>()
.AddScoped<IGroupUseCase, GroupService>()
.AddScoped<GroupController>();
}
}
}

View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\domain\domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Request\" />
<Folder Include="ServiceCollectionsExtension\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
@Presence.Api_HostAddress = http://localhost:5028
GET {{Presence.Api_HostAddress}}/weatherforecast/
Accept: application/json
###

29
Presence.Api/Program.cs Normal file
View File

@ -0,0 +1,29 @@
using Presence.Api.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCommomService();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:32613",
"sslPort": 44302
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5028",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7098;http://localhost:5028",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,9 @@
namespace Presence.Api.Response
{
public class GroupResponse
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<UserResponse>? Users { get; set; } = null;
}
}

View File

@ -0,0 +1,8 @@
namespace Presence.Api.Response
{
public class UserResponse
{
public Guid Guid { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace Presence.Api
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,10 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Presence.Desktop.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>

View File

@ -0,0 +1,37 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection;
using Presence.Desktop.DI;
using Presence.Desktop.ViewModels;
using Presence.Desktop.Views;
namespace Presence.Desktop
{
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddCommonService();
var services = serviceCollection.BuildServiceProvider();
var mainViewModel = services.GetRequiredService<GroupViewModel>();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow()
{
DataContext = new MainWindowViewModel(services),
};
}
base.OnFrameworkInitializationCompleted();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using data;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Microsoft.Extensions.DependencyInjection;
using Presence.Desktop.ViewModels;
namespace Presence.Desktop.DI
{
public static class ServiceCollectionExtensions
{
public static void AddCommonService(this IServiceCollection collection)
{
collection
.AddDbContext<RemoteDatabaseContext>()
.AddSingleton<IGroupRepository, SQLGroupRepository>()
.AddTransient<IGroupUseCase, GroupService>()
.AddTransient<GroupViewModel>();
}
}
}

View File

@ -0,0 +1,17 @@
using Avalonia.Controls;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presence.Desktop.Models
{
public class GroupPresenter
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<UserPresenter>? users { get; set; } = null;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Presence.Desktop.Models
{
public class UserPresenter
{
public Guid Guid { get; set; }
public string Name { get; set; }
public GroupPresenter Group { get; set; }
}
}

View File

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.2.1" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.1" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.1">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\data\data.csproj" />
<ProjectReference Include="..\domain\domain.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,24 @@
using Avalonia;
using Avalonia.ReactiveUI;
using System;
namespace Presence.Desktop
{
internal sealed class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
.UseReactiveUI();
}
}

View File

@ -0,0 +1,19 @@
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Presence.Desktop.ViewModels;
using System;
using Presence.Desktop.Views;
using ReactiveUI;
namespace Presence.Desktop
{
public class ViewLocator : IViewLocator
{
public IViewFor? ResolveView<T>(T? viewModel, string? contract = null) => viewModel switch
{
GroupViewModel groupViewModel => new GroupView { DataContext = groupViewModel },
PresenceViewModel presenceViewModel => new PresenceView { DataContext = presenceViewModel },
_ => throw new ArgumentOutOfRangeException(nameof(viewModel))
};
}
}

View File

@ -0,0 +1,100 @@
using domain.UseCase;
using Presence.Desktop.Models;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Presence.Desktop.ViewModels
{
public class GroupViewModel : ViewModelBase, IRoutableViewModel
{
public ICommand OpenFileDialog { get; }
public Interaction<string?, string?> SelectFileInteraction => _SelectFileInteraction;
public readonly Interaction<string?, string?> _SelectFileInteraction;
private string? _selectedFile;
public string? SelectedFile
{
get => _selectedFile;
set => this.RaiseAndSetIfChanged(ref _selectedFile, value);
}
private readonly List<GroupPresenter> _groupPresentersDataSource = new List<GroupPresenter>();
private ObservableCollection<GroupPresenter> _groups;
public ObservableCollection<GroupPresenter> Groups => _groups;
public GroupPresenter? SelectedGroupItem
{
get => _selectedGroupItem;
set => this.RaiseAndSetIfChanged(ref _selectedGroupItem, value);
}
private GroupPresenter? _selectedGroupItem;
private IGroupUseCase _groupUseCase;
public ObservableCollection<UserPresenter> Users { get => _users; }
public ObservableCollection<UserPresenter> _users;
public GroupViewModel(IGroupUseCase groupUseCase)
{
_groupUseCase = groupUseCase;
_SelectFileInteraction = new Interaction<string?, string?>();
OpenFileDialog = ReactiveCommand.CreateFromTask(SelectFile);
_users = new ObservableCollection<UserPresenter>();
RefreshGroups();
this.WhenAnyValue(vm => vm.SelectedGroupItem)
.Subscribe(_ =>
{
RefreshGroups();
SetUsers();
});
}
private void SetUsers()
{
if (SelectedGroupItem == null) return;
Users.Clear();
var group = _groups.First(it => it.Id == SelectedGroupItem.Id);
if (group.users == null) return;
foreach (var item in group.users)
{
Users.Add(item);
}
}
private void RefreshGroups()
{
_groupPresentersDataSource.Clear();
foreach (var item in _groupUseCase.GetGroupsWithStudents())
{
GroupPresenter groupPresenter = new GroupPresenter
{
Id = item.Id,
Name = item.Name,
users = item.Users?.Select(user => new UserPresenter
{
Name = user.Name,
Guid = user.Guid,
Group = new GroupPresenter { Id = item.Id, Name = item.Name }
}
).ToList()
};
_groupPresentersDataSource.Add(groupPresenter);
}
_groups = new ObservableCollection<GroupPresenter>(_groupPresentersDataSource);
}
private async Task SelectFile()
{
Console.WriteLine("clock");
SelectedFile = await _SelectFileInteraction.Handle("Chose csv file");
}
public string? UrlPathSegment { get; }
public IScreen HostScreen { get; }
}
}

View File

@ -0,0 +1,16 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using ReactiveUI;
namespace Presence.Desktop.ViewModels;
public class MainWindowViewModel : ViewModelBase, IScreen
{
public RoutingState Router { get; } = new RoutingState();
public MainWindowViewModel(IServiceProvider serviceProvider)
{
var groupViewModel = serviceProvider.GetRequiredService<GroupViewModel>();
Router.Navigate.Execute(groupViewModel);
}
}

View File

@ -0,0 +1,9 @@
using ReactiveUI;
namespace Presence.Desktop.ViewModels;
public class PresenceViewModel : ViewModelBase, IRoutableViewModel
{
public string? UrlPathSegment { get; }
public IScreen HostScreen { get; }
}

View File

@ -0,0 +1,8 @@
using ReactiveUI;
namespace Presence.Desktop.ViewModels
{
public class ViewModelBase : ReactiveObject
{
}
}

View File

@ -0,0 +1,45 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Presence.Desktop.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Presence.Desktop.Views.GroupView"
x:DataType="vm:GroupViewModel">
<Design.DataContext>
<vm:GroupViewModel/>
</Design.DataContext>
<DockPanel Background="Azure">
<StackPanel DockPanel.Dock="Bottom">
<TextBlock Text="List ↑" HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Spacing="10"
HorizontalAlignment="Center"
DockPanel.Dock="Top"
Orientation="Horizontal">
<TextBlock Text="Combobox ->"/>
<ComboBox ItemsSource="{Binding Groups}" SelectedValue="{Binding SelectedGroupItem}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Width="100" Command="{Binding OpenFileDialog}"/>
<ComboBox/>
</StackPanel>
<Border>
<ListBox Background="Bisque" ItemsSource="{Binding Users}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</DockPanel>
</UserControl>

View File

@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using Avalonia.ReactiveUI;
using Presence.Desktop.ViewModels;
using ReactiveUI;
namespace Presence.Desktop.Views
{
public partial class GroupView : ReactiveUserControl<GroupViewModel>
{
public GroupView()
{
this.WhenActivated(action =>
{
action(ViewModel!.SelectFileInteraction.RegisterHandler(ShowFileDialog));
});
AvaloniaXamlLoader.Load(this);
}
private async Task ShowFileDialog(IInteractionContext<string?, string?> context)
{
var topLevel = TopLevel.GetTopLevel(this);
var storageFile = await topLevel.StorageProvider.OpenFilePickerAsync(
new FilePickerOpenOptions()
{
AllowMultiple = false,
Title = context.Input
}
);
context.SetOutput(storageFile.First().Path.ToString());
}
}
}

View File

@ -0,0 +1,19 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:app="clr-namespace:Presence.Desktop"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Presence.Desktop.ViewModels"
xmlns:reactiveUi="http://reactiveui.net"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Presence.Desktop.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Title="MainWindow">
<DockPanel>
<reactiveUi:RoutedViewHost Router="{Binding Router}" DockPanel.Dock="Right" Background="AliceBlue">
<reactiveUi:RoutedViewHost.ViewLocator>
<app:ViewLocator/>
</reactiveUi:RoutedViewHost.ViewLocator>
</reactiveUi:RoutedViewHost>
</DockPanel>
</Window>

View File

@ -0,0 +1,18 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using Presence.Desktop.ViewModels;
using ReactiveUI;
namespace Presence.Desktop.Views;
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
public MainWindow()
{
this.WhenActivated(disposables => { });
AvaloniaXamlLoader.Load(this);
}
}

View File

@ -0,0 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Presence.Desktop.Views.PresenceView">
Welcome to Avalonia!
</UserControl>

View File

@ -0,0 +1,17 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using Presence.Desktop.ViewModels;
using ReactiveUI;
namespace Presence.Desktop.Views;
public partial class PresenceView : ReactiveUserControl<PresenceViewModel>
{
public PresenceView()
{
this.WhenActivated(disposables => { });
AvaloniaXamlLoader.Load(this);
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="Presence.Desktop.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

45
console_ui/GroupUI.cs Normal file
View File

@ -0,0 +1,45 @@
using domain.Request;
using domain.Service;
using domain.UseCase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace console_ui
{
class GroupUI
{
private readonly IGroupUseCase _groupService;
public GroupUI(IGroupUseCase groupService)
{
_groupService = groupService;
}
public void AddGroup()
{
Console.WriteLine("Enter group name: ");
_groupService.AddGroup(new domain.Request.AddGroupRequest { Name = Console.ReadLine() });
}
public void AddGroupWithStudents()
{
Console.WriteLine("Enter group name: ");
AddGroupRequest addGroupRequest = new AddGroupRequest { Name = Console.ReadLine() };
List<AddStudentRequest> addStudentRequests = new List<AddStudentRequest>()
{
new AddStudentRequest{ StudentName = "StudentName1"},
new AddStudentRequest{ StudentName = "StudentName2"},
new AddStudentRequest{ StudentName = "StudentName3"},
new AddStudentRequest{ StudentName = "StudentName4"},
};
AddGroupWithStudentsRequest addGroupWithStudents = new AddGroupWithStudentsRequest
{
addGroupRequest = addGroupRequest,
addStudentRequests = addStudentRequests
};
_groupService.AddGroupWithStudents(addGroupWithStudents);
}
}
}

View File

@ -1,2 +1,30 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
using console_ui;
using data;
using data.DAO;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Microsoft.Extensions.DependencyInjection;
void printAllGroups(IGroupRepository groupRepository)
{
Console.WriteLine("Groups:");
foreach (var item in groupRepository.getAllGroup())
{
Console.WriteLine(item.Name);
}
}
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection
.AddDbContext<RemoteDatabaseContext>()
.AddSingleton<IGroupRepository, SQLGroupRepository>()
.AddSingleton<IGroupUseCase, GroupService>()
.AddSingleton<GroupUI>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var groupUI = serviceProvider.GetService<GroupUI>();
groupUI?.AddGroup();

View File

@ -1,10 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\data\data.csproj" />
<ProjectReference Include="..\domain\domain.csproj" />
</ItemGroup>
</Project>

23
data/DAO/Attendance.cs Normal file
View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data.DAO
{
public class Attendance
{
public int AttendanceId { get; set; }
public DateOnly Date { get; set; }
public int GroupSubjectId { get; set; }
public virtual GroupSubject GroupSubject { get; set; }
public int StudentId { get; set; }
public virtual Student Student { get; set; }
public int GroupId { get; set; }
public virtual Group Group { get; set; }
public int VisitId { get; set; }
public virtual Visit Visit { get; set; }
public int LessonNumber { get; set; }
}
}

View File

@ -4,11 +4,15 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data.DAO
namespace Data.DAO
{
internal class GroupDAO
public class Group
{
public int Id { get; set; }
public String Name { get; set; }
public int GroupId { get; set; }
public string GroupName { get; set; }
public virtual IEnumerable<Student> Students { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
public virtual ICollection<GroupSubject> GroupSubjects { get; set; }
}
}

22
data/DAO/GroupSubject.cs Normal file
View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data.DAO
{
public class GroupSubject
{
public int GroupSubjectId { get; set; }
public int SemesterId { get; set; }
public virtual Semester Semester { get; set; }
public int GroupId { get; set; }
public int SubjectId { get; set; }
public virtual Group Group { get; set; }
public virtual Subject Subject { get; set; }
public virtual ICollection<Attendance> Attendances { get; set; }
}
}

17
data/DAO/Semester.cs Normal file
View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data.DAO
{
public class Semester
{
public int SemesterId { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public virtual ICollection<GroupSubject> GroupSubjects { get; set; }
}
}

19
data/DAO/Student.cs Normal file
View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data.DAO
{
public class Student
{
public int StudentId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Patronymic { get; set; }
public int GroupId { get; set; }
public virtual Group Group { get; set; }
public virtual ICollection<Attendance> Attendances { get; set; }
}
}

18
data/DAO/Subject.cs Normal file
View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data.DAO
{
public class Subject
{
public int SubjectId { get; set; }
public string SubjectName { get; set; }
public int GroupId { get; set; }
public virtual Group Group { get; set; }
public virtual ICollection<GroupSubject> GroupSubjects { get; set; }
}
}

16
data/DAO/Visit.cs Normal file
View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data.DAO
{
public class Visit
{
public int VisitId { get; set; }
public string VisitName { get; set; }
public virtual ICollection<Attendance> Attendances { get; set; }
}
}

View File

@ -0,0 +1,320 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using data;
#nullable disable
namespace data.Migrations
{
[DbContext(typeof(RemoteDatabaseContext))]
[Migration("20241212071056_InitialCreate123")]
partial class InitialCreate123
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.Property<int>("AttendanceId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("AttendanceId"));
b.Property<DateOnly>("Date")
.HasColumnType("date");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("GroupSubjectId")
.HasColumnType("integer");
b.Property<int>("LessonNumber")
.HasColumnType("integer");
b.Property<int>("StudentId")
.HasColumnType("integer");
b.Property<int>("VisitId")
.HasColumnType("integer");
b.HasKey("AttendanceId");
b.HasIndex("GroupId");
b.HasIndex("GroupSubjectId");
b.HasIndex("StudentId");
b.HasIndex("VisitId");
b.ToTable("Attendances");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Property<int>("GroupId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupId"));
b.Property<string>("GroupName")
.IsRequired()
.HasColumnType("text");
b.HasKey("GroupId");
b.ToTable("Groups");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Property<int>("GroupSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupSubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("SemesterId")
.HasColumnType("integer");
b.Property<int>("SubjectId")
.HasColumnType("integer");
b.HasKey("GroupSubjectId");
b.HasIndex("GroupId");
b.HasIndex("SemesterId");
b.HasIndex("SubjectId");
b.ToTable("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Property<int>("SemesterId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SemesterId"));
b.Property<DateTime>("EndTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("StartTime")
.HasColumnType("timestamp with time zone");
b.HasKey("SemesterId");
b.ToTable("Semesters");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Property<int>("StudentId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("StudentId"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.HasColumnType("text");
b.HasKey("StudentId");
b.HasIndex("GroupId");
b.ToTable("Students");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Property<int>("SubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("SubjectName")
.IsRequired()
.HasColumnType("text");
b.HasKey("SubjectId");
b.HasIndex("GroupId");
b.ToTable("Subjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Property<int>("VisitId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("VisitId"));
b.Property<string>("VisitName")
.IsRequired()
.HasColumnType("text");
b.HasKey("VisitId");
b.ToTable("Visits");
});
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.GroupSubject", "GroupSubject")
.WithMany("Attendances")
.HasForeignKey("GroupSubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Student", "Student")
.WithMany("Attendances")
.HasForeignKey("StudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Visit", "Visit")
.WithMany("Attendances")
.HasForeignKey("VisitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("GroupSubject");
b.Navigation("Student");
b.Navigation("Visit");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("GroupSubjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Semester", "Semester")
.WithMany("GroupSubjects")
.HasForeignKey("SemesterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Subject", "Subject")
.WithMany("GroupSubjects")
.HasForeignKey("SubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("Semester");
b.Navigation("Subject");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Students")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Subjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Navigation("GroupSubjects");
b.Navigation("Students");
b.Navigation("Subjects");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Navigation("Attendances");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,243 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate123 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Groups",
columns: table => new
{
GroupId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
GroupName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Groups", x => x.GroupId);
});
migrationBuilder.CreateTable(
name: "Semesters",
columns: table => new
{
SemesterId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
StartTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
EndTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Semesters", x => x.SemesterId);
});
migrationBuilder.CreateTable(
name: "Visits",
columns: table => new
{
VisitId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
VisitName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Visits", x => x.VisitId);
});
migrationBuilder.CreateTable(
name: "Students",
columns: table => new
{
StudentId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
FirstName = table.Column<string>(type: "text", nullable: false),
LastName = table.Column<string>(type: "text", nullable: false),
Patronymic = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Students", x => x.StudentId);
table.ForeignKey(
name: "FK_Students_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Subjects",
columns: table => new
{
SubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SubjectName = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Subjects", x => x.SubjectId);
table.ForeignKey(
name: "FK_Subjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GroupSubjects",
columns: table => new
{
GroupSubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SemesterId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
SubjectId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GroupSubjects", x => x.GroupSubjectId);
table.ForeignKey(
name: "FK_GroupSubjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Semesters_SemesterId",
column: x => x.SemesterId,
principalTable: "Semesters",
principalColumn: "SemesterId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Subjects_SubjectId",
column: x => x.SubjectId,
principalTable: "Subjects",
principalColumn: "SubjectId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Attendances",
columns: table => new
{
AttendanceId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Date = table.Column<DateOnly>(type: "date", nullable: false),
GroupSubjectId = table.Column<int>(type: "integer", nullable: false),
StudentId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
VisitId = table.Column<int>(type: "integer", nullable: false),
LessonNumber = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Attendances", x => x.AttendanceId);
table.ForeignKey(
name: "FK_Attendances_GroupSubjects_GroupSubjectId",
column: x => x.GroupSubjectId,
principalTable: "GroupSubjects",
principalColumn: "GroupSubjectId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Students_StudentId",
column: x => x.StudentId,
principalTable: "Students",
principalColumn: "StudentId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Visits_VisitId",
column: x => x.VisitId,
principalTable: "Visits",
principalColumn: "VisitId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupId",
table: "Attendances",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupSubjectId",
table: "Attendances",
column: "GroupSubjectId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_StudentId",
table: "Attendances",
column: "StudentId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_VisitId",
table: "Attendances",
column: "VisitId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_GroupId",
table: "GroupSubjects",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SemesterId",
table: "GroupSubjects",
column: "SemesterId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SubjectId",
table: "GroupSubjects",
column: "SubjectId");
migrationBuilder.CreateIndex(
name: "IX_Students_GroupId",
table: "Students",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Subjects_GroupId",
table: "Subjects",
column: "GroupId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Attendances");
migrationBuilder.DropTable(
name: "GroupSubjects");
migrationBuilder.DropTable(
name: "Students");
migrationBuilder.DropTable(
name: "Visits");
migrationBuilder.DropTable(
name: "Semesters");
migrationBuilder.DropTable(
name: "Subjects");
migrationBuilder.DropTable(
name: "Groups");
}
}
}

View File

@ -0,0 +1,320 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using data;
#nullable disable
namespace data.Migrations
{
[DbContext(typeof(RemoteDatabaseContext))]
[Migration("20241212071851_InitialCreate2")]
partial class InitialCreate2
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.Property<int>("AttendanceId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("AttendanceId"));
b.Property<DateOnly>("Date")
.HasColumnType("date");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("GroupSubjectId")
.HasColumnType("integer");
b.Property<int>("LessonNumber")
.HasColumnType("integer");
b.Property<int>("StudentId")
.HasColumnType("integer");
b.Property<int>("VisitId")
.HasColumnType("integer");
b.HasKey("AttendanceId");
b.HasIndex("GroupId");
b.HasIndex("GroupSubjectId");
b.HasIndex("StudentId");
b.HasIndex("VisitId");
b.ToTable("Attendances");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Property<int>("GroupId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupId"));
b.Property<string>("GroupName")
.IsRequired()
.HasColumnType("text");
b.HasKey("GroupId");
b.ToTable("Groups");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Property<int>("GroupSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupSubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("SemesterId")
.HasColumnType("integer");
b.Property<int>("SubjectId")
.HasColumnType("integer");
b.HasKey("GroupSubjectId");
b.HasIndex("GroupId");
b.HasIndex("SemesterId");
b.HasIndex("SubjectId");
b.ToTable("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Property<int>("SemesterId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SemesterId"));
b.Property<DateTime>("EndTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("StartTime")
.HasColumnType("timestamp with time zone");
b.HasKey("SemesterId");
b.ToTable("Semesters");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Property<int>("StudentId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("StudentId"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.HasColumnType("text");
b.HasKey("StudentId");
b.HasIndex("GroupId");
b.ToTable("Students");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Property<int>("SubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("SubjectName")
.IsRequired()
.HasColumnType("text");
b.HasKey("SubjectId");
b.HasIndex("GroupId");
b.ToTable("Subjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Property<int>("VisitId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("VisitId"));
b.Property<string>("VisitName")
.IsRequired()
.HasColumnType("text");
b.HasKey("VisitId");
b.ToTable("Visits");
});
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.GroupSubject", "GroupSubject")
.WithMany("Attendances")
.HasForeignKey("GroupSubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Student", "Student")
.WithMany("Attendances")
.HasForeignKey("StudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Visit", "Visit")
.WithMany("Attendances")
.HasForeignKey("VisitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("GroupSubject");
b.Navigation("Student");
b.Navigation("Visit");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("GroupSubjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Semester", "Semester")
.WithMany("GroupSubjects")
.HasForeignKey("SemesterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Subject", "Subject")
.WithMany("GroupSubjects")
.HasForeignKey("SubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("Semester");
b.Navigation("Subject");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Students")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Subjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Navigation("GroupSubjects");
b.Navigation("Students");
b.Navigation("Subjects");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Navigation("Attendances");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,243 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Groups",
columns: table => new
{
GroupId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
GroupName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Groups", x => x.GroupId);
});
migrationBuilder.CreateTable(
name: "Semesters",
columns: table => new
{
SemesterId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
StartTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
EndTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Semesters", x => x.SemesterId);
});
migrationBuilder.CreateTable(
name: "Visits",
columns: table => new
{
VisitId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
VisitName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Visits", x => x.VisitId);
});
migrationBuilder.CreateTable(
name: "Students",
columns: table => new
{
StudentId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
FirstName = table.Column<string>(type: "text", nullable: false),
LastName = table.Column<string>(type: "text", nullable: false),
Patronymic = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Students", x => x.StudentId);
table.ForeignKey(
name: "FK_Students_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Subjects",
columns: table => new
{
SubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SubjectName = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Subjects", x => x.SubjectId);
table.ForeignKey(
name: "FK_Subjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GroupSubjects",
columns: table => new
{
GroupSubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SemesterId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
SubjectId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GroupSubjects", x => x.GroupSubjectId);
table.ForeignKey(
name: "FK_GroupSubjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Semesters_SemesterId",
column: x => x.SemesterId,
principalTable: "Semesters",
principalColumn: "SemesterId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Subjects_SubjectId",
column: x => x.SubjectId,
principalTable: "Subjects",
principalColumn: "SubjectId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Attendances",
columns: table => new
{
AttendanceId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Date = table.Column<DateOnly>(type: "date", nullable: false),
GroupSubjectId = table.Column<int>(type: "integer", nullable: false),
StudentId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
VisitId = table.Column<int>(type: "integer", nullable: false),
LessonNumber = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Attendances", x => x.AttendanceId);
table.ForeignKey(
name: "FK_Attendances_GroupSubjects_GroupSubjectId",
column: x => x.GroupSubjectId,
principalTable: "GroupSubjects",
principalColumn: "GroupSubjectId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Students_StudentId",
column: x => x.StudentId,
principalTable: "Students",
principalColumn: "StudentId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Visits_VisitId",
column: x => x.VisitId,
principalTable: "Visits",
principalColumn: "VisitId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupId",
table: "Attendances",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupSubjectId",
table: "Attendances",
column: "GroupSubjectId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_StudentId",
table: "Attendances",
column: "StudentId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_VisitId",
table: "Attendances",
column: "VisitId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_GroupId",
table: "GroupSubjects",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SemesterId",
table: "GroupSubjects",
column: "SemesterId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SubjectId",
table: "GroupSubjects",
column: "SubjectId");
migrationBuilder.CreateIndex(
name: "IX_Students_GroupId",
table: "Students",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Subjects_GroupId",
table: "Subjects",
column: "GroupId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Attendances");
migrationBuilder.DropTable(
name: "GroupSubjects");
migrationBuilder.DropTable(
name: "Students");
migrationBuilder.DropTable(
name: "Visits");
migrationBuilder.DropTable(
name: "Semesters");
migrationBuilder.DropTable(
name: "Subjects");
migrationBuilder.DropTable(
name: "Groups");
}
}
}

View File

@ -0,0 +1,320 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using data;
#nullable disable
namespace data.Migrations
{
[DbContext(typeof(RemoteDatabaseContext))]
[Migration("20241212072022_InitialCreate2")]
partial class InitialCreate2
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.Property<int>("AttendanceId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("AttendanceId"));
b.Property<DateOnly>("Date")
.HasColumnType("date");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("GroupSubjectId")
.HasColumnType("integer");
b.Property<int>("LessonNumber")
.HasColumnType("integer");
b.Property<int>("StudentId")
.HasColumnType("integer");
b.Property<int>("VisitId")
.HasColumnType("integer");
b.HasKey("AttendanceId");
b.HasIndex("GroupId");
b.HasIndex("GroupSubjectId");
b.HasIndex("StudentId");
b.HasIndex("VisitId");
b.ToTable("Attendances");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Property<int>("GroupId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupId"));
b.Property<string>("GroupName")
.IsRequired()
.HasColumnType("text");
b.HasKey("GroupId");
b.ToTable("Groups");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Property<int>("GroupSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupSubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("SemesterId")
.HasColumnType("integer");
b.Property<int>("SubjectId")
.HasColumnType("integer");
b.HasKey("GroupSubjectId");
b.HasIndex("GroupId");
b.HasIndex("SemesterId");
b.HasIndex("SubjectId");
b.ToTable("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Property<int>("SemesterId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SemesterId"));
b.Property<DateTime>("EndTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("StartTime")
.HasColumnType("timestamp with time zone");
b.HasKey("SemesterId");
b.ToTable("Semesters");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Property<int>("StudentId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("StudentId"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.HasColumnType("text");
b.HasKey("StudentId");
b.HasIndex("GroupId");
b.ToTable("Students");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Property<int>("SubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("SubjectName")
.IsRequired()
.HasColumnType("text");
b.HasKey("SubjectId");
b.HasIndex("GroupId");
b.ToTable("Subjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Property<int>("VisitId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("VisitId"));
b.Property<string>("VisitName")
.IsRequired()
.HasColumnType("text");
b.HasKey("VisitId");
b.ToTable("Visits");
});
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.GroupSubject", "GroupSubject")
.WithMany("Attendances")
.HasForeignKey("GroupSubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Student", "Student")
.WithMany("Attendances")
.HasForeignKey("StudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Visit", "Visit")
.WithMany("Attendances")
.HasForeignKey("VisitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("GroupSubject");
b.Navigation("Student");
b.Navigation("Visit");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("GroupSubjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Semester", "Semester")
.WithMany("GroupSubjects")
.HasForeignKey("SemesterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Subject", "Subject")
.WithMany("GroupSubjects")
.HasForeignKey("SubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("Semester");
b.Navigation("Subject");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Students")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Subjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Navigation("GroupSubjects");
b.Navigation("Students");
b.Navigation("Subjects");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Navigation("Attendances");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,243 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Groups",
columns: table => new
{
GroupId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
GroupName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Groups", x => x.GroupId);
});
migrationBuilder.CreateTable(
name: "Semesters",
columns: table => new
{
SemesterId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
StartTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
EndTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Semesters", x => x.SemesterId);
});
migrationBuilder.CreateTable(
name: "Visits",
columns: table => new
{
VisitId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
VisitName = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Visits", x => x.VisitId);
});
migrationBuilder.CreateTable(
name: "Students",
columns: table => new
{
StudentId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
FirstName = table.Column<string>(type: "text", nullable: false),
LastName = table.Column<string>(type: "text", nullable: false),
Patronymic = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Students", x => x.StudentId);
table.ForeignKey(
name: "FK_Students_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Subjects",
columns: table => new
{
SubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SubjectName = table.Column<string>(type: "text", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Subjects", x => x.SubjectId);
table.ForeignKey(
name: "FK_Subjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GroupSubjects",
columns: table => new
{
GroupSubjectId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
SemesterId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
SubjectId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GroupSubjects", x => x.GroupSubjectId);
table.ForeignKey(
name: "FK_GroupSubjects_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Semesters_SemesterId",
column: x => x.SemesterId,
principalTable: "Semesters",
principalColumn: "SemesterId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_GroupSubjects_Subjects_SubjectId",
column: x => x.SubjectId,
principalTable: "Subjects",
principalColumn: "SubjectId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Attendances",
columns: table => new
{
AttendanceId = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Date = table.Column<DateOnly>(type: "date", nullable: false),
GroupSubjectId = table.Column<int>(type: "integer", nullable: false),
StudentId = table.Column<int>(type: "integer", nullable: false),
GroupId = table.Column<int>(type: "integer", nullable: false),
VisitId = table.Column<int>(type: "integer", nullable: false),
LessonNumber = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Attendances", x => x.AttendanceId);
table.ForeignKey(
name: "FK_Attendances_GroupSubjects_GroupSubjectId",
column: x => x.GroupSubjectId,
principalTable: "GroupSubjects",
principalColumn: "GroupSubjectId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Groups_GroupId",
column: x => x.GroupId,
principalTable: "Groups",
principalColumn: "GroupId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Students_StudentId",
column: x => x.StudentId,
principalTable: "Students",
principalColumn: "StudentId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Attendances_Visits_VisitId",
column: x => x.VisitId,
principalTable: "Visits",
principalColumn: "VisitId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupId",
table: "Attendances",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_GroupSubjectId",
table: "Attendances",
column: "GroupSubjectId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_StudentId",
table: "Attendances",
column: "StudentId");
migrationBuilder.CreateIndex(
name: "IX_Attendances_VisitId",
table: "Attendances",
column: "VisitId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_GroupId",
table: "GroupSubjects",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SemesterId",
table: "GroupSubjects",
column: "SemesterId");
migrationBuilder.CreateIndex(
name: "IX_GroupSubjects_SubjectId",
table: "GroupSubjects",
column: "SubjectId");
migrationBuilder.CreateIndex(
name: "IX_Students_GroupId",
table: "Students",
column: "GroupId");
migrationBuilder.CreateIndex(
name: "IX_Subjects_GroupId",
table: "Subjects",
column: "GroupId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Attendances");
migrationBuilder.DropTable(
name: "GroupSubjects");
migrationBuilder.DropTable(
name: "Students");
migrationBuilder.DropTable(
name: "Visits");
migrationBuilder.DropTable(
name: "Semesters");
migrationBuilder.DropTable(
name: "Subjects");
migrationBuilder.DropTable(
name: "Groups");
}
}
}

View File

@ -0,0 +1,317 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using data;
#nullable disable
namespace data.Migrations
{
[DbContext(typeof(RemoteDatabaseContext))]
partial class RemoteDatabaseContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.Property<int>("AttendanceId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("AttendanceId"));
b.Property<DateOnly>("Date")
.HasColumnType("date");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("GroupSubjectId")
.HasColumnType("integer");
b.Property<int>("LessonNumber")
.HasColumnType("integer");
b.Property<int>("StudentId")
.HasColumnType("integer");
b.Property<int>("VisitId")
.HasColumnType("integer");
b.HasKey("AttendanceId");
b.HasIndex("GroupId");
b.HasIndex("GroupSubjectId");
b.HasIndex("StudentId");
b.HasIndex("VisitId");
b.ToTable("Attendances");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Property<int>("GroupId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupId"));
b.Property<string>("GroupName")
.IsRequired()
.HasColumnType("text");
b.HasKey("GroupId");
b.ToTable("Groups");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Property<int>("GroupSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("GroupSubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<int>("SemesterId")
.HasColumnType("integer");
b.Property<int>("SubjectId")
.HasColumnType("integer");
b.HasKey("GroupSubjectId");
b.HasIndex("GroupId");
b.HasIndex("SemesterId");
b.HasIndex("SubjectId");
b.ToTable("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Property<int>("SemesterId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SemesterId"));
b.Property<DateTime>("EndTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("StartTime")
.HasColumnType("timestamp with time zone");
b.HasKey("SemesterId");
b.ToTable("Semesters");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Property<int>("StudentId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("StudentId"));
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.HasColumnType("text");
b.HasKey("StudentId");
b.HasIndex("GroupId");
b.ToTable("Students");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Property<int>("SubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SubjectId"));
b.Property<int>("GroupId")
.HasColumnType("integer");
b.Property<string>("SubjectName")
.IsRequired()
.HasColumnType("text");
b.HasKey("SubjectId");
b.HasIndex("GroupId");
b.ToTable("Subjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Property<int>("VisitId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("VisitId"));
b.Property<string>("VisitName")
.IsRequired()
.HasColumnType("text");
b.HasKey("VisitId");
b.ToTable("Visits");
});
modelBuilder.Entity("Data.DAO.Attendance", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany()
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.GroupSubject", "GroupSubject")
.WithMany("Attendances")
.HasForeignKey("GroupSubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Student", "Student")
.WithMany("Attendances")
.HasForeignKey("StudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Visit", "Visit")
.WithMany("Attendances")
.HasForeignKey("VisitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("GroupSubject");
b.Navigation("Student");
b.Navigation("Visit");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("GroupSubjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Semester", "Semester")
.WithMany("GroupSubjects")
.HasForeignKey("SemesterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Data.DAO.Subject", "Subject")
.WithMany("GroupSubjects")
.HasForeignKey("SubjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
b.Navigation("Semester");
b.Navigation("Subject");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Students")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.HasOne("Data.DAO.Group", "Group")
.WithMany("Subjects")
.HasForeignKey("GroupId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Group");
});
modelBuilder.Entity("Data.DAO.Group", b =>
{
b.Navigation("GroupSubjects");
b.Navigation("Students");
b.Navigation("Subjects");
});
modelBuilder.Entity("Data.DAO.GroupSubject", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Semester", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Student", b =>
{
b.Navigation("Attendances");
});
modelBuilder.Entity("Data.DAO.Subject", b =>
{
b.Navigation("GroupSubjects");
});
modelBuilder.Entity("Data.DAO.Visit", b =>
{
b.Navigation("Attendances");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,51 @@
using Data.DAO;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data
{
public class RemoteDatabaseContext: DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql("Host=localhost;port=5432;Password=admin;Username=postgres;Database=semesterWork");
}
//protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
//{
// optionsBuilder.UseNpgsql("Host=45.67.56.214; Port=5454; Username=user3; Password=VOTfZ8PQ; Database=user3");
//}
public DbSet<Group> Groups { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<Attendance> Attendances { get; set; }
public DbSet<GroupSubject> GroupSubjects { get; set; }
public DbSet<Semester> Semesters { get; set; }
public DbSet<Subject> Subjects { get; set; }
public DbSet<Visit> Visits { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().HasKey(it => it.StudentId);
modelBuilder.Entity<Group>().HasKey(it => it.GroupId);
modelBuilder.Entity<GroupSubject>().HasKey(it => it.GroupSubjectId);
modelBuilder.Entity<Semester>().HasKey(it => it.SemesterId);
modelBuilder.Entity<Visit>().HasKey(it => it.VisitId);
modelBuilder.Entity<Subject>().HasKey(it => it.SubjectId);
modelBuilder.Entity<Attendance>().HasKey(it => it.AttendanceId);
modelBuilder.Entity<Student>().Property(it => it.StudentId).ValueGeneratedOnAdd();
modelBuilder.Entity<Group>().Property(it => it.GroupId).ValueGeneratedOnAdd();
modelBuilder.Entity<GroupSubject>().Property(it => it.GroupSubjectId).ValueGeneratedOnAdd();
modelBuilder.Entity<Semester>().Property(it => it.SemesterId).ValueGeneratedOnAdd();
modelBuilder.Entity<Visit>().Property(it => it.VisitId).ValueGeneratedOnAdd();
modelBuilder.Entity<Subject>().Property(it => it.SubjectId).ValueGeneratedOnAdd();
modelBuilder.Entity<Attendance>().Property(it => it.AttendanceId).ValueGeneratedOnAdd();
}
}
}

View File

@ -0,0 +1,63 @@
using Data.DAO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data.Repository
{
public interface IGroupRepository
{
public IEnumerable<Group> GetAllGroup();
public bool AddGroup(Group group);
public bool addGroupWithStudent(Group groups, IEnumerable<Student> students);
public bool DeleteGroup(int groupId);
public Group GetGroupWithSubjects(int groupId);
public void AddStudentsToGroup(List<Student> students);
public Group GetGroupById(int groupId);
public Subject GetSubjectById(int subjectId);
public Subject GetSubjectByName(string subjectName);
public void AddSubject(Subject subject);
List<Subject> GetGroupSubjects(int groupId);
List<Subject> GetSubjectsByGroupId(int groupId);
bool AddSubjectToGroup(int groupId, Subject subject);
public void DeleteAllAttendances();
public void DeleteAttendancesByGroup(int groupId);
void AddAttendance(Attendance attendance);
Visit GetVisitById(int visitId);
int GetGroupIdBySubjectName(string subjectName);
public IEnumerable<Attendance> GetAttendances(int groupId, string subject = null, DateTime? date = null, int? studentId = null);
Attendance GetAttendanceByDateStudentAndLesson(DateTime date, int studentId, int lessonNumber);
void UpdateAttendance(Attendance attendance);
void RemoveStudentsFromGroup(int groupId);
void RemoveStudentsFromGroupByIds(int groupId, List<int> studentIds);
}
}

View File

@ -0,0 +1,347 @@
using Data.DAO;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data.Repository
{
public class SQLGroupRepository : IGroupRepository
{
private readonly RemoteDatabaseContext _dbContext;
public SQLGroupRepository(RemoteDatabaseContext remoteDatabaseContext) { _dbContext = remoteDatabaseContext; }
public bool AddGroup(Group group)
{
var maxGroupId = _dbContext.Groups.Max(g => (int?)g.GroupId) ?? 0;
group.GroupId = maxGroupId + 1;
_dbContext.Groups.Add(group);
return _dbContext.SaveChanges() > 0;
}
public bool addGroupWithStudent(Group groups, IEnumerable<Student> students)
{
using var transaction = _dbContext.Database.BeginTransaction();
try
{
_dbContext.Groups.Add(groups);
_dbContext.SaveChanges();
_dbContext.Groups.Add(groups);
foreach (var item in students)
{
item.Group = groups;
_dbContext.Students.Add(item);
}
_dbContext.SaveChanges();
transaction.Commit();
return true;
}
catch (Exception ex)
{
transaction.Rollback();
Console.WriteLine(ex.Message);
return false;
}
}
public void AddStudentsToGroup(List<Student> students)
{
var maxStudentId = _dbContext.Students.Max(s => (int?)s.StudentId) ?? 0;
foreach (var student in students)
{
student.StudentId = ++maxStudentId;
}
_dbContext.Students.AddRange(students);
_dbContext.SaveChanges();
}
public bool DeleteGroup(int groupId)
{
using var transaction = _dbContext.Database.BeginTransaction();
try
{
var group = _dbContext.Groups
.Include(g => g.Students)
.FirstOrDefault(g => g.GroupId == groupId);
if (group != null)
{
_dbContext.Students.RemoveRange(group.Students);
_dbContext.Groups.Remove(group);
_dbContext.SaveChanges();
transaction.Commit();
return true;
}
return false;
}
catch
{
transaction.Rollback();
throw;
}
}
public IEnumerable<Group> GetAllGroup()
{
return _dbContext.Groups
.Include(group => group.Students)
.Include(group => group.GroupSubjects)
.ThenInclude(gs => gs.Subject)
.ToList();
}
public Group GetGroupById(int groupId)
{
return _dbContext.Groups
.Include(group => group.Students)
.Include(group => group.Subjects)
.FirstOrDefault(group => group.GroupId == groupId);
}
public Group GetGroupWithSubjects(int groupId)
{
return _dbContext.Groups
.Include(group => group.Subjects)
.FirstOrDefault(group => group.GroupId == groupId);
}
public void AddSubjectsToGroup(List<GroupSubject> groupSubjects)
{
using var transaction = _dbContext.Database.BeginTransaction();
try
{
foreach (var groupSubject in groupSubjects)
{
var group = _dbContext.Groups.Include(g => g.Subjects).FirstOrDefault(g => g.GroupId == groupSubject.GroupId);
if (group == null)
{
throw new KeyNotFoundException($"Group with ID {groupSubject.GroupId} not found.");
}
var subject = _dbContext.Subjects.FirstOrDefault(s => s.SubjectId == groupSubject.SubjectId);
if (subject == null)
{
throw new KeyNotFoundException($"Group with ID {groupSubject.SubjectId} not found.");
}
if (!group.Subjects.Any(s => s.SubjectId == subject.SubjectId))
{
group.Subjects.Add(subject);
}
}
_dbContext.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
public Subject GetSubjectById(int subjectId)
{
return _dbContext.Subjects.FirstOrDefault(s => s.SubjectId == subjectId);
}
public Subject GetSubjectByName(string subjectName)
{
return _dbContext.Subjects.FirstOrDefault(s => s.SubjectName == subjectName);
}
public void AddSubject(Subject subject)
{
_dbContext.Subjects.Add(subject);
_dbContext.SaveChanges();
}
public List<Subject> GetGroupSubjects(int groupId)
{
return _dbContext.Groups
.Where(group => group.GroupId == groupId)
.SelectMany(group => group.Subjects)
.ToList();
}
public Subject GetSubjectByGroup(int subjectId)
{
var groupSubject = _dbContext.GroupSubjects
.Include(gs => gs.Subject)
.FirstOrDefault(gs => gs.SubjectId == subjectId);
if (groupSubject == null || groupSubject.Subject == null)
{
throw new KeyNotFoundException($"Предмет с ID {subjectId} не найден.");
}
return groupSubject.Subject;
}
public List<Subject> GetSubjectsByGroupId(int groupId)
{
var group = _dbContext.Groups
.Include(g => g.GroupSubjects)
.ThenInclude(gs => gs.Subject)
.FirstOrDefault(g => g.GroupId == groupId);
if (group == null)
{
throw new KeyNotFoundException($"Группа с ID {groupId} не найдена.");
}
return group.GroupSubjects
.Select(gs => gs.Subject)
.ToList();
}
public bool AddSubjectToGroup(int groupId, Subject subject)
{
using (var transaction = _dbContext.Database.BeginTransaction())
{
try
{
var group = _dbContext.Groups.Include(g => g.Subjects).FirstOrDefault(g => g.GroupId == groupId);
if (group == null)
{
transaction.Rollback();
return false;
}
int maxSubjectId = _dbContext.Subjects.Any()
? _dbContext.Subjects.Max(s => s.SubjectId)
: 0;
subject.SubjectId = maxSubjectId + 1;
subject.Group = group;
_dbContext.Subjects.Add(subject);
_dbContext.SaveChanges();
transaction.Commit();
return true;
}
catch (Exception)
{
transaction.Rollback();
throw;
}
}
}
public void DeleteAllAttendances()
{
using var context = new RemoteDatabaseContext();
var allAttendances = context.Attendances.ToList();
context.Attendances.RemoveRange(allAttendances);
context.SaveChanges();
}
public void DeleteAttendancesByGroup(int groupId)
{
using var context = new RemoteDatabaseContext();
var attendancesByGroup = context.Attendances.Where(a => a.GroupId == groupId).ToList();
context.Attendances.RemoveRange(attendancesByGroup);
context.SaveChanges();
}
public void AddAttendance(Attendance attendance)
{
_dbContext.Attendances.Add(attendance);
_dbContext.SaveChanges();
}
public Visit GetVisitById(int visitId)
{
return _dbContext.Visits.FirstOrDefault(v => v.VisitId == visitId);
}
public int GetGroupIdBySubjectName(string subjectName)
{
var subject = _dbContext.Subjects.Include(s => s.Group)
.FirstOrDefault(s => s.SubjectName == subjectName);
if (subject == null || subject.Group == null)
{
throw new InvalidOperationException($"Предмет с названием '{subjectName}' или его группа не найдены.");
}
return subject.Group.GroupId;
}
public IEnumerable<Attendance> GetAttendances(int groupId, string subject = null, DateTime? date = null, int? studentId = null)
{
var query = _dbContext.Attendances.AsQueryable();
query = query.Where(a => a.GroupId == groupId);
if (!string.IsNullOrEmpty(subject))
{
query = query.Where(a => a.GroupSubject.Subject.SubjectName == subject);
}
if (date.HasValue)
{
var dateOnly = DateOnly.FromDateTime(date.Value);
query = query.Where(a => a.Date == dateOnly);
}
if (studentId.HasValue)
{
query = query.Where(a => a.StudentId == studentId.Value);
}
return query.ToList();
}
public Attendance GetAttendanceByDateStudentAndLesson(DateTime date, int studentId, int lessonNumber)
{
var dateOnly = DateOnly.FromDateTime(date);
return _dbContext.Attendances
.FirstOrDefault(a => a.Date == dateOnly && a.StudentId == studentId && a.LessonNumber == lessonNumber);
}
public void UpdateAttendance(Attendance attendance)
{
_dbContext.Attendances.Update(attendance);
_dbContext.SaveChanges();
}
public void RemoveStudentsFromGroup(int groupId)
{
var students = _dbContext.Students.Where(s => s.GroupId == groupId).ToList();
_dbContext.Students.RemoveRange(students);
_dbContext.SaveChanges();
}
public void RemoveStudentsFromGroupByIds(int groupId, List<int> studentIds)
{
var studentsToRemove = _dbContext.Students
.Where(s => s.GroupId == groupId && studentIds.Contains(s.StudentId))
.ToList();
if (studentsToRemove.Any())
{
_dbContext.Students.RemoveRange(studentsToRemove);
_dbContext.SaveChanges();
}
}
}
}

View File

@ -1,9 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Migrations\**" />
<EmbeddedResource Remove="Migrations\**" />
<None Remove="Migrations\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.10">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.10" />
</ItemGroup>
</Project>

7
domain/Class1.cs Normal file
View File

@ -0,0 +1,7 @@
namespace domain
{
public class Class1
{
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Entity
{
public class GroupEntity
{
public int Id { get; set; }
public string Name { get; set; }
public List<UserEntity> Users { get; set; } = null;
}
}

View File

@ -4,13 +4,12 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data.DAO
namespace domain.Entity
{
internal class User
public class UserEntity
{
public Guid Guid { get; set; }
public string Name { get; set; }
public virtual GroupDAO Group { get; set; }
public GroupEntity Group { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Request
{
public class AddGroupRequest
{
public string Name { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Request
{
public class AddGroupWithStudentsRequest
{
public AddGroupRequest addGroupRequest { get; set; }
public IEnumerable<AddStudentRequest> addStudentRequests { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Request
{
public class AddStudentRequest
{
public string StudentName { get; set; }
}
}

View File

@ -0,0 +1,79 @@
using data.DAO;
using data.Repository;
using domain.Entity;
using domain.Request;
using domain.UseCase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Service
{
public class GroupService : IGroupUseCase
{
private readonly IGroupRepository _groupRepository;
public GroupService(IGroupRepository groupRepository)
{
_groupRepository = groupRepository;
}
public void AddGroup(AddGroupRequest addGroupRequest)
{
_groupRepository.addGroup(new data.DAO.GroupDAO { Name = addGroupRequest.Name });
}
public void AddGroupWithStudents(AddGroupWithStudentsRequest addGroupWithStudents)
{
GroupDAO groupDAO = new GroupDAO() { Name = addGroupWithStudents.addGroupRequest.Name };
List<UserDAO> users = addGroupWithStudents.addStudentRequests
.Select(it => new UserDAO { Name = it.StudentName })
.ToList();
_groupRepository.addGroupWithStudents(groupDAO, users);
}
public IEnumerable<GroupEntity> GetGroupsWithStudents()
{
return _groupRepository.getAllGroup().Select(
group => new GroupEntity()
{
Id = group.Id,
Name = group.Name,
Users = group.Users.Select(
user => new UserEntity
{
Guid = user.Guid,
Name = user.Name,
Group = new GroupEntity
{
Id = group.Id,
Name = group.Name,
}
}).ToList()
}).ToList();
}
public async Task<IEnumerable<GroupEntity>> GetGroupsWithStudentsAsync()
{
var result = await _groupRepository.getAllGroupAsync();
return result.Select(
group => new GroupEntity
{
Id = group.Id,
Name = group.Name,
Users = group.Users.Select(
user => new UserEntity
{
Guid = user.Guid,
Name = user.Name,
Group = new GroupEntity
{
Id = group.Id,
Name = group.Name,
}
}).ToList()
}).ToList();
}
}
}

View File

@ -0,0 +1,18 @@
using domain.Entity;
using domain.Request;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.UseCase
{
public interface IGroupUseCase
{
public IEnumerable<GroupEntity> GetGroupsWithStudents();
public Task<IEnumerable<GroupEntity>> GetGroupsWithStudentsAsync();
public void AddGroup(AddGroupRequest addGroupRequest);
public void AddGroupWithStudents(AddGroupWithStudentsRequest addGroupWithStudents);
}
}

17
domain/domain.csproj Normal file
View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Response\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\data\data.csproj" />
</ItemGroup>
</Project>

View File

@ -3,9 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "console_ui", "console_ui\console_ui.csproj", "{C66F54DD-3684-4790-87A7-A36355AB0BC7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "console_ui", "console_ui\console_ui.csproj", "{C66F54DD-3684-4790-87A7-A36355AB0BC7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "data", "data\data.csproj", "{28FE5F1E-5D2B-4750-AE24-A15BB8A5972D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "data", "data\data.csproj", "{28FE5F1E-5D2B-4750-AE24-A15BB8A5972D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "domain", "domain\domain.csproj", "{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Presence.Api", "Presence.Api\Presence.Api.csproj", "{0493354A-C0C0-49FC-A143-28F2268309E2}"
ProjectSection(ProjectDependencies) = postProject
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63} = {78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Presence.Desktop", "Presence.Desktop\Presence.Desktop.csproj", "{D646BC7E-8025-4985-AF9B-5E4474AD7F66}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -21,6 +30,18 @@ Global
{28FE5F1E-5D2B-4750-AE24-A15BB8A5972D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28FE5F1E-5D2B-4750-AE24-A15BB8A5972D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28FE5F1E-5D2B-4750-AE24-A15BB8A5972D}.Release|Any CPU.Build.0 = Release|Any CPU
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78C8AC9B-2B4D-4C71-8469-C6DAE16C9A63}.Release|Any CPU.Build.0 = Release|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0493354A-C0C0-49FC-A143-28F2268309E2}.Release|Any CPU.Build.0 = Release|Any CPU
{D646BC7E-8025-4985-AF9B-5E4474AD7F66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D646BC7E-8025-4985-AF9B-5E4474AD7F66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D646BC7E-8025-4985-AF9B-5E4474AD7F66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D646BC7E-8025-4985-AF9B-5E4474AD7F66}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE