-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
persistence v3 mongo #228
base: main
Are you sure you want to change the base?
persistence v3 mongo #228
Changes from all commits
9ec9d46
7753a39
f333ec0
393ac57
ca400b4
1f252ed
783839b
2aaacb5
e98035d
f379dd1
433abaa
4517e31
e172a33
8544b84
7ac7d50
4d02201
0349a11
3496d02
1f7c178
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/mongo | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
version: '3.8' | ||
services: | ||
mongodb: | ||
image: mongo | ||
hostname: "mongo" | ||
restart: always | ||
volumes: | ||
- ./mongo/data:/data/db | ||
ports: | ||
- '27017:27017' | ||
environment: | ||
- MONGO_INITDB_ROOT_USERNAME=mongo | ||
- MONGO_INITDB_ROOT_PASSWORD=mongo |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ | |
}, | ||
"AasxServerBlazor": { | ||
"commandName": "Project", | ||
"commandLineArgs": "--no-security --secret-string-api 1234 --aasx-in-memory 1000 --data-path \"C:\\Development\\Ronny\" --edit --external-blazor http://localhost:5001", | ||
"commandLineArgs": "--no-security --aasx-in-memory 1000 --data-path \"C:\\GitClones\\aasx-server\\content-for-demo\\aasxs\" --edit --external-blazor http://localhost:5001 --with-mongodb \"mongodb://mongo:mongo@localhost:27017/\"", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please revert the changes for --data-path |
||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
dotnet AasxServerBlazor.dll --no-security --data-path ./aasxs --host 0.0.0.0 $OPTIONSAASXSERVER | ||
dotnet AasxServerBlazor.dll --no-security --aasx-in-memory 1000 --data-path ./aasxs --edit --external-blazor http://localhost:5001 --with-mongodb "mongodb://mongo:mongo@mongodb-server:27017/" $OPTIONSAASXSERVER |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,8 @@ | |
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.13.1" /> | ||
<PackageReference Include="MongoDB.Driver" Version="2.25.0" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the license for these package checked, to be compatible with the open source guidelines? |
||
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.25.0" /> | ||
<PackageReference Include="MQTTnet.NETStandard" Version="3.0.8" /> | ||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" /> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
using MongoDB.Bson.Serialization.Serializers; | ||
using MongoDB.Bson.Serialization; | ||
using MongoDB.Driver; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using AasxServerStandardBib.Exceptions; | ||
using MongoDB.Bson; | ||
using MongoDB.Driver.Linq; | ||
using System.Collections; | ||
using AasCore.Aas3_0; | ||
using AdminShellNS; | ||
using MongoDB.Driver.GridFS; | ||
using static AasxServerStandardBib.TimeSeriesPlotting.PlotArguments; | ||
using System.IO; | ||
|
||
|
||
//Author: Jonas Graubner | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't use personalised author tags. I know that we do not have a template for that yet, but creating your own one will be harder to resolve in the end. All your commits can be viewed in the git history and if you want to add yourself as a contributor, you can add a new entry in the CONTRIBUTORS.md |
||
//contact: [email protected] | ||
namespace AasxServerStandardBib | ||
{ | ||
public interface IDatabase | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please avoid creating multiple classes/interfaces in a single file. This is considered a Code Smell. Although this exists in other parts of the project, let's not add new instances. More info: Code Smell #228: Multiple Classes per File |
||
{ | ||
void Initialize(String connectionString); | ||
|
||
#region AssetAdministrationShell | ||
public void WriteDBAssetAdministrationShell(IAssetAdministrationShell shell); | ||
public IQueryable<AssetAdministrationShell> GetLINQAssetAdministrationShell(); | ||
public void UpdateDBAssetAdministrationShellById(IAssetAdministrationShell body, string aasIdentifier); | ||
public bool DeleteDBAssetAdministrationShellById(IAssetAdministrationShell shell); | ||
#endregion | ||
|
||
#region Submodel | ||
public void WriteDBSubmodel(ISubmodel submodel); | ||
public IQueryable<Submodel> GetLINQSubmodel(); | ||
public void UpdateDBSubmodelById(string submodelIdentifier, ISubmodel newSubmodel); | ||
public void DeleteDBSubmodelById(string submodelIdentifier); | ||
#endregion | ||
|
||
#region ConceptDescription | ||
public void WriteDBConceptDescription(IConceptDescription conceptDescription); | ||
public IQueryable<ConceptDescription> GetLINQConceptDescription(); | ||
public void UpdateDBConceptDescriptionById(IConceptDescription newConceptDescription, string cdIdentifier); | ||
public void DeleteDBConceptDescriptionById(string conceptDescription); | ||
#endregion | ||
|
||
#region Filestream | ||
public void WriteFile(Stream stream, string filename); | ||
public Stream ReadFile(string filename); | ||
public void DeleteFile(string filename); | ||
#endregion | ||
|
||
public void importAASCoreEnvironment(IEnvironment environment); | ||
public void importAdminShellPackageEnv(AdminShellPackageEnv adminShellPackageEnv); | ||
} | ||
|
||
|
||
public class MongoDatabase : IDatabase | ||
{ | ||
private MongoClient _client; | ||
private IMongoDatabase _database; | ||
private GridFSBucket _bucket; | ||
|
||
public void Initialize(String connectionString) | ||
{ | ||
//_client = new MongoClient("mongodb://AAS:[email protected]:27017/?authSource=AAS"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't commit commented code. If you think this might be useful information as an example, please create a valid c# method summary |
||
_client = new MongoClient(connectionString); | ||
try | ||
{ | ||
_client.StartSession(); | ||
} | ||
catch (System.TimeoutException ex) | ||
{ | ||
System.Console.WriteLine(ex.Message); | ||
System.Environment.Exit(1); | ||
} | ||
|
||
_database = _client.GetDatabase("AAS"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the values like For more information, see Code Smell: Magic Numbers. |
||
var objectSerializer = new ObjectSerializer(type => ObjectSerializer.DefaultAllowedTypes(type) || type.FullName.StartsWith("AasCore") || type.FullName.StartsWith("MongoDB")); | ||
BsonSerializer.RegisterSerializer(objectSerializer); | ||
_bucket = new GridFSBucket(_database, new GridFSBucketOptions | ||
{ | ||
BucketName = "aasxFiles", | ||
}); | ||
} | ||
private IMongoCollection<AssetAdministrationShell> getAasCollection() | ||
{ | ||
return _database.GetCollection<AssetAdministrationShell>("AssetAdministrationShells"); | ||
} | ||
private IMongoCollection<Submodel> getSubmodelCollection() | ||
{ | ||
return _database.GetCollection<Submodel>("Submodels"); | ||
} | ||
private IMongoCollection<ConceptDescription> getConceptDescriptionCollection() | ||
{ | ||
return _database.GetCollection<ConceptDescription>("ConceptDescriptions"); | ||
} | ||
|
||
|
||
#region AssetAdministrationShell | ||
public void WriteDBAssetAdministrationShell(IAssetAdministrationShell shell) | ||
{ | ||
try | ||
{ | ||
getAasCollection().InsertOne((AssetAdministrationShell)shell); | ||
} | ||
catch (MongoWriteException) | ||
{ | ||
} | ||
} | ||
public bool DeleteDBAssetAdministrationShellById(IAssetAdministrationShell shell) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
public IQueryable<AssetAdministrationShell> GetLINQAssetAdministrationShell() | ||
{ | ||
return getAasCollection().AsQueryable(); | ||
} | ||
public async void UpdateDBAssetAdministrationShellById(IAssetAdministrationShell body, string aasIdentifier) | ||
{ | ||
await getAasCollection().ReplaceOneAsync(r => r.Id.Equals(aasIdentifier), (AssetAdministrationShell)body); | ||
} | ||
#endregion | ||
|
||
#region Submodel | ||
public void WriteDBSubmodel(ISubmodel submodel) | ||
{ | ||
try | ||
{ | ||
getSubmodelCollection().InsertOne((Submodel)submodel); | ||
} | ||
catch (MongoWriteException) | ||
{ | ||
} | ||
} | ||
public IQueryable<Submodel> GetLINQSubmodel() | ||
{ | ||
return getSubmodelCollection().AsQueryable(); | ||
} | ||
public async void UpdateDBSubmodelById(string submodelIdentifier, ISubmodel newSubmodel) | ||
{ | ||
await getSubmodelCollection().ReplaceOneAsync(r => r.Id.Equals(submodelIdentifier), (Submodel)newSubmodel); | ||
} | ||
public async void DeleteDBSubmodelById(string submodelIdentifier) | ||
{ | ||
await getSubmodelCollection().DeleteOneAsync(a => a.Id.Equals(submodelIdentifier)); | ||
} | ||
#endregion | ||
|
||
#region ConceptDescription | ||
public void WriteDBConceptDescription(IConceptDescription conceptDescription) | ||
{ | ||
try | ||
{ | ||
getConceptDescriptionCollection().InsertOne((ConceptDescription)conceptDescription); | ||
} | ||
catch (MongoWriteException) | ||
{ | ||
} | ||
} | ||
public IQueryable<ConceptDescription> GetLINQConceptDescription() | ||
{ | ||
return getConceptDescriptionCollection().AsQueryable(); | ||
} | ||
public async void UpdateDBConceptDescriptionById(IConceptDescription newConceptDescription, string cdIdentifier) | ||
{ | ||
await getConceptDescriptionCollection().ReplaceOneAsync(r => r.Id.Equals(cdIdentifier), (ConceptDescription)newConceptDescription); | ||
} | ||
public async void DeleteDBConceptDescriptionById(string conceptDescription) | ||
{ | ||
await getConceptDescriptionCollection().DeleteOneAsync(a => a.Id.Equals(conceptDescription)); | ||
} | ||
#endregion | ||
|
||
#region Filestream | ||
public async void WriteFile(Stream stream, string filename) | ||
{ | ||
if (stream != null) | ||
{ | ||
Console.WriteLine("New File"); | ||
var id = await _bucket.UploadFromStreamAsync(filename, stream); | ||
stream.Close(); | ||
}else | ||
{ | ||
//throw new ArgumentNullException(nameof(stream)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's important to handle exceptions appropriately rather than commenting them out. In your Best practice dictates that exceptions should be handled or propagated correctly to maintain application reliability and provide meaningful error messages for debugging. Commenting out exceptions can obscure issues and make troubleshooting more difficult, which is considered a code smell. To improve, consider either uncommenting the exception handling and adding appropriate logging or refactor the method to handle null |
||
} | ||
} | ||
public Stream ReadFile(string filename) | ||
{ | ||
return _bucket.OpenDownloadStream(getFileIdFromFilename(filename)); | ||
} | ||
|
||
public async void DeleteFile(string filename) | ||
{ | ||
ObjectId fileId = getFileIdFromFilename(filename); | ||
await _bucket.DeleteAsync(fileId); | ||
} | ||
|
||
private ObjectId getFileIdFromFilename(string filename) | ||
{ | ||
var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, filename); | ||
var sort = Builders<GridFSFileInfo>.Sort.Descending(x => x.UploadDateTime); | ||
var options = new GridFSFindOptions | ||
{ | ||
Limit = 1, | ||
Sort = sort | ||
}; | ||
|
||
using (var cursor = _bucket.Find(filter, options)) | ||
{ | ||
var fileInfo = cursor.ToList().FirstOrDefault(); | ||
// fileInfo either has the matching file information or is null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could rather be used as a method summary. /// <summary>
/// Retrieves the ObjectId of the latest file matching the specified filename in the GridFS bucket.
/// </summary>
/// <param name="filename">The filename of the file to retrieve.</param>
/// <returns>The ObjectId of the matching file, or ObjectId.Empty if no matching file is found.</returns> |
||
return fileInfo.Id; | ||
} | ||
} | ||
|
||
|
||
#endregion | ||
|
||
|
||
public void importAASCoreEnvironment(IEnvironment environment) | ||
{ | ||
environment.AssetAdministrationShells.ForEach(shell => { | ||
WriteDBAssetAdministrationShell(shell); | ||
}); | ||
|
||
environment.Submodels.ForEach(submodel => | ||
{ | ||
WriteDBSubmodel(submodel); | ||
}); | ||
|
||
environment.ConceptDescriptions.ForEach(conceptDescription => | ||
{ | ||
WriteDBConceptDescription(conceptDescription); | ||
}); | ||
} | ||
|
||
public void importAdminShellPackageEnv(AdminShellPackageEnv adminShellPackageEnv) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the standard C# naming for methods, which is PascalCase please |
||
{ | ||
importAASCoreEnvironment(adminShellPackageEnv.AasEnv); | ||
|
||
//now import Files | ||
var files = adminShellPackageEnv.GetListOfSupplementaryFiles(); | ||
var assetid = adminShellPackageEnv.AasEnv.AssetAdministrationShells[0].AssetInformation.GlobalAssetId; //unique identifier | ||
foreach ( var file in files ) | ||
{ | ||
if (file.Location == AdminShellNS.AdminShellPackageSupplementaryFile.LocationType.InPackage) | ||
{ | ||
WriteFile(adminShellPackageEnv.GetLocalStreamFromPackage(file.Uri.ToString()), assetid+file.Uri.ToString()); | ||
//ReadFile(assetid + file.Uri.ToString()); | ||
} | ||
} | ||
|
||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need a new gitignore here. That should also be configurable in the existing gitignore