Working on db access

This commit is contained in:
Max Holleman 2023-06-02 10:56:30 +02:00
parent 1f0e8840c1
commit 4ef3b58a20
6 changed files with 117 additions and 76 deletions

View File

@ -4,6 +4,7 @@ using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;
using Argotic.Syndication;
using Dapper;
using Microsoft.Data.Sqlite;
@ -42,7 +43,7 @@ namespace SharpRss
using SqliteDataReader countReader = await cmdFeedCount.ExecuteReaderAsync();
int count = countReader.Read() ? countReader.GetInt32(0) : 0;
groups.Add(new CategoryModel()
groups.Add(new CategoryModel()
{
Name = reader["name"].ToString(),
FeedCount = count,
@ -78,7 +79,7 @@ namespace SharpRss
bool result = false;
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
// Remove the group and remove the feeds that were part of the group.
// Remove the group and remove the feeds that were part of the group.
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {GroupTable} WHERE id=@id; UPDATE {FeedTable} SET group_id=NULL WHERE group_id=@id", dbc)
{
Parameters =
@ -125,45 +126,86 @@ namespace SharpRss
{
Parameters = { new SqliteParameter("Url", url) }
};
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
if (reader.Read())
feed = await ReaderToFeedModel(reader);
try
{
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
if (reader.Read())
feed = await ReaderToFeedModel(reader);
}
catch (Exception ex)
{
Log.Error(ex, "Error while fetching feed from db.");
}
return feed;
}
public static async Task<FeedModel?> SetFeedsAsync(IEnumerable<FeedModel> feedModels)
public static async Task<FeedModel?> SetFeedAsync(FeedModel feedModel)
{
//TODO: Implement fetching system!!!
FeedModel? resultModel = null;
FeedModel? feed = null;
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteTransaction transaction = dbc.BeginTransaction();
foreach (var feedModel in feedModels)
await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {FeedTable} (url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (@url, @title, @groupId, @feedType, @description, @language, @copyright, @dateAdded), @lastUpdated, @imageUrl, @originalDoc); SELECT * FROM {FeedTable} WHERE url=@url", dbc)
{
//await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {_feedTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc); SELECT * FROM {_feedTable} WHERE url=@url", dbc)
await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {FeedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {FeedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {FeedTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc)", dbc)
Parameters =
{
Parameters =
{
new SqliteParameter("id", feedModel.Id ?? string.Empty),
new SqliteParameter("url", feedModel.Url ?? string.Empty),
new SqliteParameter("title", feedModel.Title ?? string.Empty),
new SqliteParameter("groupId", feedModel.GroupId ?? string.Empty),
new SqliteParameter("feedType", feedModel.FeedType ?? string.Empty),
new SqliteParameter("description", feedModel.Description ?? string.Empty),
new SqliteParameter("language", feedModel.Language ?? string.Empty),
new SqliteParameter("copyright", feedModel.Copyright ?? string.Empty),
new SqliteParameter("dateAdded", feedModel.DateAdded?.ToUnixTimeMilliseconds()),
new SqliteParameter("lastUpdated", feedModel.LastUpdated?.ToUnixTimeMilliseconds()),
new SqliteParameter("imageUrl", feedModel.ImageUrl ?? string.Empty),
new SqliteParameter("originalDoc", feedModel.OriginalDocument ?? string.Empty)
},
Transaction = transaction
};
await cmd.ExecuteNonQueryAsync();
new SqliteParameter("url", feedModel.Url ?? string.Empty),
new SqliteParameter("title", feedModel.Title ?? string.Empty),
new SqliteParameter("groupId", feedModel.GroupId ?? string.Empty),
new SqliteParameter("feedType", feedModel.FeedType ?? string.Empty),
new SqliteParameter("description", feedModel.Description ?? string.Empty),
new SqliteParameter("language", feedModel.Language ?? string.Empty),
new SqliteParameter("copyright", feedModel.Copyright ?? string.Empty),
new SqliteParameter("dateAdded", feedModel.DateAdded?.ToUnixTimeMilliseconds()),
new SqliteParameter("lastUpdated", feedModel.LastUpdated?.ToUnixTimeMilliseconds()),
new SqliteParameter("imageUrl", feedModel.ImageUrl ?? string.Empty),
new SqliteParameter("originalDoc", feedModel.OriginalDocument ?? string.Empty)
}
};
try
{
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
feed = await ReaderToFeedModel(reader);
}
await transaction.CommitAsync();
await FetchFeedItemsAsync(feedModels.Select(x => x.Url).ToArray());
return resultModel;
catch (Exception ex)
{
Log.Error(ex, "Database error, adding feed model to database failed!");
return feed;
}
return feed;
/*await using SqliteTransaction transaction = dbc.BeginTransaction();
try
{
foreach (var feedModel in feedModels)
{
//await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {_feedTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc); SELECT * FROM {_feedTable} WHERE url=@url", dbc)
await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {FeedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {FeedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {FeedTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc)", dbc)
{
Parameters =
{
new SqliteParameter("id", feedModel.Id ?? string.Empty),
new SqliteParameter("url", feedModel.Url ?? string.Empty),
new SqliteParameter("title", feedModel.Title ?? string.Empty),
new SqliteParameter("groupId", feedModel.GroupId ?? string.Empty),
new SqliteParameter("feedType", feedModel.FeedType ?? string.Empty),
new SqliteParameter("description", feedModel.Description ?? string.Empty),
new SqliteParameter("language", feedModel.Language ?? string.Empty),
new SqliteParameter("copyright", feedModel.Copyright ?? string.Empty),
new SqliteParameter("dateAdded", feedModel.DateAdded?.ToUnixTimeMilliseconds()),
new SqliteParameter("lastUpdated", feedModel.LastUpdated?.ToUnixTimeMilliseconds()),
new SqliteParameter("imageUrl", feedModel.ImageUrl ?? string.Empty),
new SqliteParameter("originalDoc", feedModel.OriginalDocument ?? string.Empty)
},
Transaction = transaction
};
await cmd.ExecuteNonQueryAsync();
}
await transaction.CommitAsync();
}
catch (Exception ex)
{
await transaction.RollbackAsync();
Log.Error(ex, "Error on inserting feeds to db.");
return false;
}*/
}
public static async Task FetchFeedItemsAsync(string[]? feedUrls = null)
@ -188,8 +230,8 @@ namespace SharpRss
{
GenericSyndicationFeed syndication = new GenericSyndicationFeed();
syndication.Load(dbFeed.OriginalDocument);
//TODO: Get items and add to db
}
//TODO: Rewrite some stuff...
}
public static async Task<bool> RemoveFeedAsync(FeedModel feedModel)
@ -197,11 +239,11 @@ namespace SharpRss
bool result = false;
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {FeedTable} WHERE id=@id; UPDATE {FeedItemTable} SET feed_id=NULL WHERE feed_id=@id", dbc)
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {FeedTable} WHERE url=@Url; UPDATE {FeedItemTable} SET feed_id=NULL WHERE feed_id=@Url", dbc)
{
Parameters =
{
new SqliteParameter("id", feedModel.Id)
new SqliteParameter("Url", feedModel.Url)
}
};
int affected = await cmd.ExecuteNonQueryAsync();
@ -280,10 +322,10 @@ namespace SharpRss
dbc.Open();
int affected = await cmd.ExecuteNonQueryAsync();
if (affected == 0)
Log.Verbose("Could not set feed item: {FeedLink}", item.Link);
Log.Verbose("Could not set feed item: {FeedLink}", item.Link);
else
result += affected;
}
result += affected;
}
transaction.Commit();
return result;
}
@ -326,9 +368,9 @@ namespace SharpRss
}
private static async Task<FeedModel> ReaderToFeedModel(SqliteDataReader reader)
{
FeedModel fetchedFeed = new FeedModel(reader["url"].ToString())
FeedModel fetchedFeed = new FeedModel()
{
Id = reader["id"].ToString(),
Url = reader["url"].ToString(),
Title = reader["title"].ToString(),
GroupId = reader["group_id"].ToString(),
FeedType = reader["feed_type"].ToString(),
@ -340,14 +382,15 @@ namespace SharpRss
ImageUrl = reader["image_url"].ToString(),
OriginalDocument = reader["original_document"].ToString()
};
var groupFetch = await GetGroupsAsync(fetchedFeed.GroupId);
//TODO: Set group on insert
/*var groupFetch = await GetGroupsAsync(fetchedFeed.GroupId);
if (groupFetch.Any())
fetchedFeed.Group = groupFetch.First();
else
Log.Warning("Could not get group from feed: {FeedId}", fetchedFeed.Id);
Log.Warning("Could not get group from feed: {FeedId}", fetchedFeed.Id);*/
return fetchedFeed;
}
//===
public static async void Initialize()
{
@ -359,7 +402,7 @@ namespace SharpRss
Log.Verbose("Checking table: {Table}", "category");
var queryResponse = await dbc.QueryAsync("CREATE TABLE IF NOT EXISTS category (name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING, id STRING PRIMARY KEY)");
if (queryResponse.Any()) failed.Add("category");
Log.Verbose("Checking table: {Table}", "feed");
queryResponse = await dbc.QueryAsync($"CREATE TABLE IF NOT EXISTS feed (url STRING PRIMARY KEY, title STRING, group_id STRING, feed_type STRING, description STRING, language STRING, copyright STRING, date_added INT, last_updated INT, image_url STRING, original_document STRING)");
if (queryResponse.Any()) failed.Add("feed");
@ -367,7 +410,7 @@ namespace SharpRss
Log.Verbose("Checking table: {Table}", "feed_item");
queryResponse = await dbc.QueryAsync($"CREATE TABLE IF NOT EXISTS feed_item (id STRING PRIMARY KEY, feed_id STRING, read INT, title STRING, description STRING, link STRING, last_updated INT, publishing_date INT, author STRING, categories STRING, content STRING)");
if (queryResponse.Any()) failed.Add("feed_item");
if (failed.Any())
{
var joined = string.Join(',', failed);

View File

@ -4,13 +4,11 @@ namespace SharpRss.Models
{
public class FeedModel
{
public FeedModel(string rssUrl)
public FeedModel()
{
Url = rssUrl;
}
public CategoryModel? Group { get; set; }
public string? Id { get; set; }
public string? Url { get; set; }
public string Url { get; set; }
public string? Title { get; set; } = string.Empty;
public string? GroupId { get; set; } = string.Empty;
public string? FeedType { get; set; } = string.Empty;

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Threading.Tasks;
using Argotic.Common;
@ -38,35 +39,33 @@ namespace SharpRss.Services
bool validate = SyndicationDiscoveryUtility.UriExists(new Uri(url));
if (!validate) return false;
// Check if feed exists in db
FeedModel? dbFeed = await DbAccess.GetFeedAsync(url);
if (dbFeed == null)
FeedModel? fModel = await DbAccess.GetFeedAsync(url);
// If not exists fetch feed & add.
if (fModel == null)
{
GenericSyndicationFeed genFeed = new GenericSyndicationFeed();
switch (genFeed.Format)
{
case SyndicationContentFormat.Rss:
RssFeed rssFeed = (RssFeed)genFeed.Resource;
break;
case SyndicationContentFormat.Atom:
AtomFeed atomFeed = (AtomFeed)genFeed.Resource;
break;
default:
Log.Information("Feed implementation missing!");
break;
}
GenericSyndicationFeed genFeed = GenericSyndicationFeed.Create(new Uri(url));
fModel = FromResource(genFeed.Resource);
fModel.GroupId = group?.Id;
// Add feed
FeedModel? dbFeed = await DbAccess.SetFeedAsync(fModel);
// Update/fetch items
await DbAccess.FetchFeedItemsAsync(new string[] { fModel.Url });
}
// Update feed if newer
// Update/fetch items
return false;
}
private static FeedModel FromResource(ISyndicationResource resource)
{
FeedModel model = new FeedModel("");
switch (resource)
FeedModel model = new FeedModel();
switch (resource.Format)
{
case RssFeed rssFeed:
//TODO: From feed to model
case SyndicationContentFormat.Rss:
RssFeed rssFeed = (RssFeed)resource;
break;
case SyndicationContentFormat.Atom:
AtomFeed atomFeed = (AtomFeed)resource;
break;
default:
Log.Information("Feed implementation missing!");
break;
}
return model;
@ -158,8 +157,9 @@ namespace SharpRss.Services
Log.Error(e, "Error fetching feeds!");
throw;
}*/
var groups = await GetGroupsAsync();
CategoryModel testGroup = groups.Single(x => x.Name == "News");
/*var groups = await GetGroupsAsync();
CategoryModel testGroup = groups.Single(x => x.Name == "News");*/
await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen");
/*await AddFeedsAsync(new[]
{
"https://www.nu.nl/rss/Algemeen",

View File

@ -57,7 +57,7 @@
else if (Gid != null)
{
var feeds = await _rssService.GetFeedsAsync(Gid);
var feedIds = feeds.Select(x => x.Id);
var feedIds = feeds.Select(x => x.Url);
var feedItems = await _rssService.GetFeedItemsFromFeedsAsync(feedIds.ToArray());
items = feedItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
}

View File

@ -51,7 +51,7 @@
if (_selectedItem == null) return;
if (_selectedItem.FeedModel != null)
{
_navigation.NavigateTo($"/list?fid={_selectedItem.FeedModel.Id}");
_navigation.NavigateTo($"/list?fid={_selectedItem.FeedModel.Url}");
}
else if (_selectedItem.GroupModel != null)
{

Binary file not shown.