FMMultiFieldMapper 0.2.0

dotnet add package FMMultiFieldMapper --version 0.2.0                
NuGet\Install-Package FMMultiFieldMapper -Version 0.2.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FMMultiFieldMapper" Version="0.2.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add FMMultiFieldMapper --version 0.2.0                
#r "nuget: FMMultiFieldMapper, 0.2.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install FMMultiFieldMapper as a Cake Addin
#addin nuget:?package=FMMultiFieldMapper&version=0.2.0

// Install FMMultiFieldMapper as a Cake Tool
#tool nuget:?package=FMMultiFieldMapper&version=0.2.0                

build and test

FileMaker MultiField mapper

This library maps data between FileMaker-based DTO objects and relational database objects. The focus is on multi-fields that are easily filterable.

Installation

You can install the library via NuGet:

dotnet add package FMMultiFieldMapper

Sample Usage

Implementing FmMultiFieldMap

To use the FmMultiFieldMapper, you need to implement the abstract FmMultiFieldMap class.

internal class InMemoryFmMultiFieldMapper(TestContext context) : FmMultiFieldMap
{
    public override async Task<int> GetOrCreateMultiFieldId(string name)
    {
        var id = await context.Multifields
            .Where(x => x.Name == name)
            .Select(s => s.FmMultiFieldId)
            .FirstOrDefaultAsync();

        if (id == 0)
        {
            var multifield = new FmMultiField() { Name = name };
            context.Multifields.Add(multifield);
            await context.SaveChangesAsync();
            id = multifield.FmMultiFieldId;
        }
        return id;
    }

    public override async Task<int> GetOrCreateMultiFieldValueId(int multifieldId, string value)
    {
        var id = await context.MultifieldValues
            .Where(x => x.FmMultiFieldId == multifieldId && x.Value == value)
            .Select(s => s.FmMultiFieldValueId)
            .FirstOrDefaultAsync();

        if (id == 0)
        {
            var multifieldValue = new FmMultiFieldValue()
            {
                FmMultiFieldId = multifieldId,
                Value = value
            };
            context.MultifieldValues.Add(multifieldValue);
            await context.SaveChangesAsync();
            id = multifieldValue.FmMultiFieldValueId;
        }
        return id;
    }
}

Mapping FileMaker Objects to Relational Database Objects

Below is an example of how to map a FileMaker object (FmSourceTestClass) to a relational database object (FmTargetTestClassMultifield).

[DataContract(Name = "TestLayout")]
public class FmSourceTestClass
{
    [NotMapped]
    public int FileMakerRecordId { get; set; }
    [DataMember(Name = "Themen(1)")]
    [FileMakerMultiField(MultiFieldName = "Themen", Order = 0)]
    public string? Themen1 { get; set; }
    [DataMember(Name = "Themen(2)")]
    [FileMakerMultiField(MultiFieldName = "Themen", Order = 1)]
    public string? Themen2 { get; set; }
    [DataMember(Name = "Themen(3)")]
    [FileMakerMultiField(MultiFieldName = "Themen", Order = 2)]
    public string? Themen3 { get; set; }
}

public class FmTargetTestClassMultifield : IFmTargetMultiField
{
    public int FmTargetTestClassMultifieldId { get; set; }
    public int FmMultiFieldId { get; set; }
    public FmMultiField? FmMultiField { get; set; }
    public int FmMultiFieldValueId { get; set; }
    public FmMultiFieldValue? FmMultiFieldValue { get; set; }
    public int FmTargetTestClassId { get; set; }
    public FmTargetTestClass? FmTargetTestClass { get; set; }
    public int Order { get; set; }
}

var target = _dbContext.FmTargetTestClasses.FirstOrDefault();

var source = new FmSourceTestClass()
{
    Themen1 = "Test3",
    Themen2 = "Test4",
    Themen3 = "Test5"
};

InMemoryFmMultiFieldMapper mapper = new(_dbContext);
await mapper.Map(source, target.FmTargetTestClassMultifields);
_dbContext.SaveChanges();

DTO mapping

You can also map data from a DTO object to your database entities using Dictionary<string, List<string>>

Here's how you can map a FmTargetTestClassDto to FmTargetTestClass:

FmTargetTestClassDto dto = new()
{
    FmTargetTestClassMultifields = new()
    {
        { "Themen", ["Test1", "Test2", "Test3"] },
        { "Was", ["WTest1", "WTest2", "WTest3"] },
    }
};

CacheFmMultiFieldMapper mapper = new(_dbContext);

FmTargetTestClass fmTargetTestClass = new();
_dbContext.FmTargetTestClasses.Add(fmTargetTestClass);
_dbContext.SaveChanges();

await mapper.MapFromDtoDictionary(dto.FmTargetTestClassMultifields, fmTargetTestClass.FmTargetTestClassMultifields);
_dbContext.SaveChanges();

var fmTargetTestClassWithIncludes = _dbContext.FmTargetTestClasses
    .Include(i => i.FmTargetTestClassMultifields)
        .ThenInclude(t => t.FmMultiField)
    .Include(i => i.FmTargetTestClassMultifields)
        .ThenInclude(t => t.FmMultiFieldValue)
    .FirstOrDefault(f => f.Id == fmTargetTestClass.Id);

Assert.IsNotNull(fmTargetTestClassWithIncludes);
Assert.AreEqual(6, fmTargetTestClassWithIncludes.FmTargetTestClassMultifields.Count);

FmTargetTestClassDto testDto = new();
testDto.FmTargetTestClassMultifields = FmMultiFieldMap
    .GetDtoDictionary(fmTargetTestClassWithIncludes.FmTargetTestClassMultifields);

Assert.AreEqual(dto.FmTargetTestClassMultifields.Count, testDto.FmTargetTestClassMultifields.Count);

All samples are available in the test project located at .src/FMMultifieldMapperTests.

FmSyncService

Synchronize IFmObject to IFmDbObject based on FileMakerRecordId, modification date and synchronization date

Sample implementation

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please open an issue or submit a pull request. Make sure to follow the coding standards and include tests for any new features or bug fixes.

ChangeLog

<details open="open"><summary>v0.2.0</summary>

  • FmMultiFieldMap.GetDtoDictionary added
  • FmMultiFieldMap.MapToDtoDictionary marked as Obsolete: Use GetDtoDictionary instead
  • abstract class FmSyncService Synchronize IFmObject to IFmDbObject based on FileMakerRecordId, modification date and synchronization date.
  • FmSyncTests

</details>

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.2.0 111 9/2/2024
0.1.0 101 8/29/2024