Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
LongSack
Jan 17, 2003

SirViver posted:

The issue arises because you use a DLL/assembly reference to the output of a project in your solution instead of using a project reference - without explicitly telling VS that there is a dependency it doesn't know that the project happens to generate the referenced DLL*. The consequence of this is that VS will happily compile both projects in parallel instead of the actual required build order, resulting in a race condition of whether the referenced DLL will still (or already) exist when the referencing project is built.

Usually this results in weird build errors where a namespace that clearly exists cannot be found during compilation or where a DLL mysteriously cannot be copied to the output folder. I guess the Pack URI mechanism needs to access the source assemblies at some point during compilation and silently fails if it can't, resulting in broken resource images.

* Technically it likely could deduce that is the case, but honestly it's probably better it doesn't. Unless such heuristics are rock solid they just lead to random issues or broken behavior in edge cases. At most I'd have VS generate a clippy-like notification that it detected this case and whether to fix it, but not automagically assume stuff behind the scenes.

Thanks!

Adbot
ADBOT LOVES YOU

Macichne Leainig
Jul 26, 2012

by VG
I’m banging my head against a tasking issue and would like a sanity check since this whole thing uses AppDomains, tasks, async/await and whatnot which I all conceptually understand but not very well in practice.

To describe the software solution: we have a 3rd party reporting utility. A need arised to be able to cancel the generation of a report. One of the devs on my team worked with one of our architects to come up with this solution that creates a new AppDomain for each report in the request, loads the generation request into a task, awaits Task.WhenAny, and when the task is completed it will add it to the list of byte arrays representing what will be the final PDF or Excel doc.

Now, it’s not working properly. The workflow terminates as soon as ANY report is received, meaning if a request contains three reports, it only generates report 1 and sends that document out to the destination.

I think it makes more sense to create one single AppDomain for the request and reuse the instance from the CreateInstanceAndUnwrap method (the report generator is instantiated in this method). I feel like creating multiple AppDomains for this request is complicating the bug somewhat. Does that make any sense? It seems like we’re doubling the workload by making a new AppDomain and then using it to spool off a generation task where it just seems more appropriate to only make one for the request.

Also, when awaiting Task.WhenAny, is it possible to make it wait until every task is complete (or cancelled) before moving onto something else?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Protocol7 posted:

Also, when awaiting Task.WhenAny, is it possible to make it wait until every task is complete (or cancelled) before moving onto something else?

WhenAll?

Macichne Leainig
Jul 26, 2012

by VG

Ah yeah, that’s in there too but it’s not awaited. Is that all I’d need to change? It is called before WhenAny, if that matters.

EssOEss
Oct 23, 2006
128-bit approved
Post code.

Macichne Leainig
Jul 26, 2012

by VG

EssOEss posted:

Post code.

Ok, here's the whole shabang, the first part is the part that creates the AppDomain, second part is checking the tasks:

code:
List<Task<Tuple<Guid, Byte[]>>> tasklist = new List<Task<Tuple<Guid, byte[]>>>();

for (int i = 0; i < thisRequest.Reports.Count; i++)
{
	Report currentReport = thisRequest.Reports[i];
	Guid appDomainGuid = Guid.NewGuid();

	AppDomainSetup appSetup = AppDomain.CurrentDomain.SetupInformation;
	appSetup.ApplicationBase = Path.GetFullPath(appSetup.ApplicationBase + @"..\..\Binaries");
	AppDomain currAppdomain = AppDomain.CreateDomain(appDomainGuid.ToString(), null, appSetup);

	ReportGenerator reportGenerator = (ReportGenerator)currAppdomain.CreateInstanceAndUnwrap(typeof(ReportGenerator).Assembly.FullName, typeof(ReportGenerator).FullName);
	reportAppDomains.Add(currentReport.ReportID, currAppdomain);

	Task<Tuple<Guid, Byte[]>> reportTask = reportGenerator.Generate(thisRequest.RequestID, currentReport.ReportID, currentReport.ReportFormat, thisRequest.RequestorUserID);
	reportIDList.Add(currentReport.ReportID);
	tasklist.Add(reportTask);

	UpdateReportRequestInfo(thisRequest.RequestID, currentReport.ReportID, ReportRequestInfoStatus.In_Progress, thisRequest.RequestorUserID);
}

Task<bool> isCanceledTask = IsAnyReportRequestCanceledAsync(thisRequest.RequestID, reportIDList);
var allReportTask = Task.WhenAll(tasklist);
var taskCompleted = await Task.WhenAny(isCanceledTask, allReportTask);

//check if is cancel task completed first
if (taskCompleted.Id == isCanceledTask.Id) 
{
	if (((Task<bool>)taskCompleted).Result == true)
	{
		foreach (Guid reportid in reportIDList)
		{
			if (reportAppDomains.ContainsKey(reportid))
			{
				try
				{
					AppDomain currReportAppDomain = reportAppDomains[reportid];
					AppDomain.Unload(currReportAppDomain);
					UpdateReportRequestInfo(thisRequest.RequestID, reportid, ReportRequestInfoStatus.Cancel_Complete, thisRequest.RequestorUserID);
				}
				catch { }
			}
		}
	}
}
else
{
	if (taskCompleted.Id == allReportTask.Id)
	{
		Task<Tuple<Guid, Byte[]>[]> reportResults = (Task<Tuple<Guid, Byte[]>[]>)taskCompleted;

		foreach (var report in reportResults.Result)
		{
			if (report != null && report.Item2 != null)
			{
				result.Add(report.Item2);
				UpdateReportRequestInfo(thisRequest.RequestID, report.Item1, ReportRequestInfoStatus.Complete, thisRequest.RequestorUserID);
			}
		}
	}
}
So with this one, the final result.Add(report.Item2) is called once, then it appears to continue on and returns the result variable with only the first completed item in the result list.

The whole shabang is wrapped in a try/catch/finally where in the finally it goes through all the app domains and unloads them.

Looking at this in SA's code viewer is just making me want to purge it all and redo it... all of those unnecessarily nested ifs... time to reinstall Resharper.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
That code has multiple issues. You know something has gone wrong when you're using the type List<Task<Tuple<Guid, Byte[]>>> (at the very least turn that tuple into a real type), and if (((Task<bool>)taskCompleted).Result == true) is a bad line in several ways.

I might be missing something here, but could this not be implemented by sharing a CancellationToken between all the tasks and calling ThrowIfCancellationRequested in the appropriate spot(s)? Then the act of cancelling becomes a simple matter of calling await Task.WhenAll(tasks) and triggering the CancellationToken when the user requests it. It would require reportGenerator.Generate to take the CancellationToken as input, so if you don't control that code you might be out of luck.

In the current version of the code, putting await in front of the Task.WhenAll will cause the program to wait until all the tasks in the list are finished regardless of cancellation, so that won't solve your problem. Are you ending up inside if (taskCompleted.Id == isCanceledTask.Id) when the task ends prematurely? If so, IsAnyReportRequestCanceledAsync is the culprit. If you're ending up in the else-block at the bottom it should be because all the tasks in tasklist have finished. If they're always finishing even though only one of them is done it could be because the tasks are sharing their state somehow. It's hard to tell exactly why from here.

Macichne Leainig
Jul 26, 2012

by VG
We do own the "Report Generator" class, so I can totally add a cancellation token to that. That sounds like, 20x better and it's a lot more clear looking at the code that the workflow supports cancellation in that way. I got some similar feedback from an architect too, telling me my peer didn't work too closely with an architect on this project. :doh:

Fake edit:
Almost done refactoring this guy's code... here's a preview of the diff in VS.



Less is more, my friend... less is more.

Macichne Leainig fucked around with this message at 21:14 on Oct 22, 2018

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Anyone else had a VS update remove the Python paths that (I'm pretty sure) VS sets up? Tried to use Python on the command line just now and it's not found. It's not in PATH, PYTHONPATH is missing entirely, Conda isn't in PATH, etc. I'm not even sure what to make them to fix this and my kludges aren't working. This is also impossible to google because Conda has its own environment management stuff so that's all I get results for :sigh:

Mr Shiny Pants
Nov 12, 2012
I have multiple background task running in my F# application and I was wondering if the following setup is the way to go:

code:
let startServer (port:int32) token =
    async {
        let client = 
            let c = new UdpClient(port)
            let multicastGroup = IPAddress.Parse("239.0.0.222")
            c.JoinMulticastGroup(multicastGroup)
            c
    
    
        let rec listen (client:UdpClient) = 
            async {
                let ep = ref null
                let endRcv msg = client.EndReceive(msg, ep)
                let! msg = Async.FromBeginEnd(client.BeginReceive, endRcv)
                processPacket msg Config.Id
                return! listen(client)
                }
        
        return! listen(client)
    }


let rec ListenInput() =
    async {
        printfn "Input"
        match Console.ReadLine() |> fun x -> x.Split(' ') with
        | [|"exit"|] ->
            cts.Cancel()
            Environment.Exit(0)
        | [|"config"|] ->
            printfn "Running configuration: %A" Config
            return! ListenInput()
        | _ ->
            printfn "Not handled yet"
            return! ListenInput()
    }


[<EntryPoint>]
let main argv =
    [startServer Config.Port cts.Token; ListenInput()]
    |> Async.Parallel
    |> Async.RunSynchronously
    |> ignore
    0
I had a couple of Async Starts in there before and refactored it into this. I like it, I was just wondering if I am missing something glaringly obvious.

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison
Is there a decent logging abstraction that works for net45 and netstandard2? I’ve got a library that multi-targets but commons.logging, liblog, etc. won’t play nice

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

uncurable mlady posted:

Is there a decent logging abstraction that works for net45 and netstandard2? I’ve got a library that multi-targets but commons.logging, liblog, etc. won’t play nice

Serilog is .NET Standard 1.3 so it runs on everything. It's pretty well designed, too.

Mr Shiny Pants posted:

I have multiple background task running in my F# application and I was wondering if the following setup is the way to go:

I had a couple of Async Starts in there before and refactored it into this. I like it, I was just wondering if I am missing something glaringly obvious.

My multiple-webservices-plus-background-jobs app looks almost exactly the same. I just have some error handling boilerplate around it:

code:

[<EntryPoint>]
let main args = 
  try
    let cfg : Configuration = // read arguments and configuration here
    let enabledServices : (Configuration -> int) seq = // decide which services to run based on the options provided
    [ for service in enabledServices -> async { return service(options) } ]
    |> Async.Parallel 
    |> Async.RunSynchronously
    |> Array.tryFind (fun errorCode -> errorCode <> 0)
    |> Option.defaultValue 0
    
  with
  | exn ->
      let color = Console.ForegroundColor
      Console.ForegroundColor <- ConsoleColor.Red
      Console.WriteLine(exn.Message)
      Console.ForegroundColor <- color
#if DEBUG
      Console.ReadLine() |> ignore
#endif  
      exn.HResult

Mr Shiny Pants
Nov 12, 2012

Thanks. I guess the Array.tryFind checks to see if a service returns a non zero result on startup? I might borrow that. :)

EssOEss
Oct 23, 2006
128-bit approved
After failing to provide .NET Framework SDKs that can properly utilize .NET Standard libraries for 3 years, after going back and forth about ASP.NET Core support on .NET Framework, after waiting a few years for people to get used to .NET Core, Microsoft is finally trying again to come out and say that .NET Framework is in maintenance mode and should not be used for new development.

At least that is my reading of it. I guess it had to happen some day.

Macichne Leainig
Jul 26, 2012

by VG
I thought I read that a while ago, have they really been waffling for so long?

mystes
May 31, 2006

Protocol7 posted:

I thought I read that a while ago, have they really been waffling for so long?
I think it was pretty clear that it was supposed to be the way forward for ASP, but in general I don't think it was clear that .net core was supposed to entirely replace .net framework until the last few months.

It still won't be possible to use .net core for wpf apps until .net core 3 comes out in Q1 2019.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

Protocol7 posted:

I thought I read that a while ago, have they really been waffling for so long?

They tried to do it with ASP.NET Core 2.0, but received massive pushback and chickened out. This time it should happen for real.

Macichne Leainig
Jul 26, 2012

by VG
I guess I shouldn't be surprised, Microsoft has a history of trying to push people off older tech and getting pushback.

Drastic Actions
Apr 7, 2009

FUCK YOU!
GET PUMPED!
Nap Ghost

LOOK I AM A TURTLE posted:

They tried to do it with ASP.NET Core 2.0, but received massive pushback and chickened out. This time it should happen for real.

At least with 3.x it feels more "earned", 2.x could work just fine on .NET Framework with some modifications so introducing a breaking change there didn't make much sense. Trying the same with what they want to do with 3.x doesn't look possible.

They're still gonna get poo poo for it, :shrug:

mystes
May 31, 2006

The average .net user is probably still mad that they discontinued legacy VB.

B-Nasty
May 25, 2005

It seems obvious that .NET Framework is next on the chopping block. I'm putting it out there: 4.8.x will be the last release.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
Has anyone here used Xamarin? Would you recommend it for a cross-platform app?

Ensign Expendable
Nov 11, 2008

Lager beer is proof that god loves us
Pillbug
Yes and yes. Forms is really good now.

kloa
Feb 14, 2007


Is Blazor worth getting in to, or does everyone just use Angular and React these days with .NET?

mystes
May 31, 2006

kloa posted:

Is Blazor worth getting in to, or does everyone just use Angular and React these days with .NET?
I don't think Blazor is considered ready for production?

EssOEss
Oct 23, 2006
128-bit approved
Yeah, Blazor is just a neat toy. Play around with it if you like but don't expect it to be usable for anything beyond a todolist app.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Ensign Expendable posted:

Yes and yes. Forms is really good now.

OK, I'm giving it a go. Code sharing strategy: .NET Standard or Shared Project? I can't see any upside to .NET Standard - if I understand correctly, it's the "lowest common denominator" approach, which I just can't see working well for an end-user application

beuges
Jul 4, 2005
fluffy bunny butterfly broomstick

hackbunny posted:

OK, I'm giving it a go. Code sharing strategy: .NET Standard or Shared Project? I can't see any upside to .NET Standard - if I understand correctly, it's the "lowest common denominator" approach, which I just can't see working well for an end-user application

It depends on what sort of app you're building, I think. If you're going to mostly be using common controls (text entries, buttons, labels, pickers, etc) then Xamarin Forms and netstandard is the simplest from a dev perspective. Yes you build to the lowest common denominator, but it keeps your code simpler. If you want to add in additional functionality per platform then you can do so by building the platform-specific code in your platform-specific project as a custom renderer, or by injecting an interface to your platform-specific featureset when you create your new platform-agnostic App().
You can still do a lot of UI customization with Xamarin Forms though. If you need to render your own bitmaps for stuff, look at SkiaSharp. Then there's also Xamarin.Essentials which adds a whole lot of additional APIs.

mst4k
Apr 18, 2003

budlitemolaram

mystes posted:

The average .net user is probably still mad that they discontinued legacy VB.

VB.Net developers make like 50% more than I do in my market because they have to maintain horrible legacy systems started in the mid 2000s for the state government, lol.

B-Nasty
May 25, 2005

karma_coma posted:

VB.Net developers make like 50% more than I do in my market because they have to maintain horrible legacy systems started in the mid 2000s for the state government, lol.

VB.NET is heaven on earth compared to old VB (a.k.a. VB6) and its web cousin, ASP Classic. VB.NET is just the same .NET as C#, but with an ugly, retarded syntax.

In fairness though, even VB6/Classic ASP wasn't a horrible language, and it was actually very powerful. Its real issue was that it was easy for non-programmers to use. That sounds good on paper, but once you get an application beyond trivial complexity/functionality, organization of code, DRY, standard patterns/practices, etc. starts to become really important. God help whoever has to maintain a 100K+LOC VB application cobbled together by someone who never programmed before.

redleader
Aug 18, 2005

Engage according to operational parameters

B-Nasty posted:

VB.NET is heaven on earth compared to old VB (a.k.a. VB6) and its web cousin, ASP Classic. VB.NET is just the same .NET as C#, but with an ugly, retarded syntax.

In fairness though, even VB6/Classic ASP wasn't a horrible language, and it was actually very powerful. Its real issue was that it was easy for non-programmers to use. That sounds good on paper, but once you get an application beyond trivial complexity/functionality, organization of code, DRY, standard patterns/practices, etc. starts to become really important. God help whoever has to maintain a 100K+LOC VB application cobbled together by someone who never programmed before.

In other words, classic ASP suffers from PHP Syndrome.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

B-Nasty posted:

VB.NET is heaven on earth compared to old VB (a.k.a. VB6) and its web cousin, ASP Classic. VB.NET is just the same .NET as C#, but with an ugly, retarded syntax.

In fairness though, even VB6/Classic ASP wasn't a horrible language, and it was actually very powerful. Its real issue was that it was easy for non-programmers to use. That sounds good on paper, but once you get an application beyond trivial complexity/functionality, organization of code, DRY, standard patterns/practices, etc. starts to become really important. God help whoever has to maintain a 100K+LOC VB application cobbled together by someone who never programmed before.

yeah, one of the reasons why asp team started pushing mvc is that legacy asp apps tended towards ball of mud one tier architecture with zero test-ability.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

beuges posted:

It depends on what sort of app you're building, I think. If you're going to mostly be using common controls (text entries, buttons, labels, pickers, etc) then Xamarin Forms and netstandard is the simplest from a dev perspective.

Initially, yes, but I don't want to get hamstrung by it as the application becomes more complex

beuges posted:

Yes you build to the lowest common denominator, but it keeps your code simpler. If you want to add in additional functionality per platform then you can do so by building the platform-specific code in your platform-specific project as a custom renderer, or by injecting an interface to your platform-specific featureset when you create your new platform-agnostic App().
You can still do a lot of UI customization with Xamarin Forms though. If you need to render your own bitmaps for stuff, look at SkiaSharp. Then there's also Xamarin.Essentials which adds a whole lot of additional APIs.

It's not the customizations I'm worried about (the longer I can avoid them, the better), it's more the fact that I won't get platform ifdefs with a .NET Standard project, if I understand correctly. Is there an easy way out, should I start with a .NET Standard project but then realize I need platform-specific code?

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

hackbunny posted:

It's not the customizations I'm worried about (the longer I can avoid them, the better), it's more the fact that I won't get platform ifdefs with a .NET Standard project, if I understand correctly. Is there an easy way out, should I start with a .NET Standard project but then realize I need platform-specific code?

Define an interface IMyPlatformSpecificStuff with whatever calls you need, implement it in both applications and pass it to the common library.

power crystals
Jun 6, 2007

Who wants a belly rub??

Is it possible to define a method via CodeDOM where the containing class is built "normally" but the method body is written in IL? The only thing I can find that takes IL and generates executable code is DynamicMethod, and I guess I could have stub methods that call those, but that seems silly. Well, more silly than this idea already is.

Roslyn also acceptable if it's possible to do it without having to use Core since everything I can find on how you actually use that for this is Core specific.

(This is for a personal project that I'm doing for the sake of it, nobody but me will ever be forced to interact with that abomination if it works)

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!
So I've ran into an issue trying to think of a good solution for the following problem, and I could use some general advice. Problem looks like this:

Model:
code:
 public class File
    {
        public Guid Id { get; set; }
        [Required]
        [StringLength(255)]
        public string FileName { get; set; }
        [Required]
        public byte[] Data { get; set; }

        public DateTime TimeStamp { get; set; }
    }

public class Image : File 
{}

public class Audio : File
{}
This simple File model is the basis for an EF context for storing files. As a file can have many types, I originally created a context that looks something like this:

code:
        public DbSet<Image> Images { get; set; }
        public DbSet<Audio> Audio { get; set; }
And of course, the service call

code:
private void MyGenericUploadMethod(IFormFileCollection files)
using (_context.Database.BeginTransaction())
            {
               //A BUNCH OF BULLSHIT HERE WHO CARES
		 _context.??????.Add(...); // <=== _context.Images? _context.Audio? _context.SlashFanFicts? I DONT KNOW
            }
        }
Here's the problem: the _context for EF needs to specify the property related to the table I want to use. If I have N file types I wish to store, I will need N service calls for N properties on _context, which literally all do the same thing, wrap transaction logic.

I could probably create a base class, but I can't find a way to create a more generic Upload method. I've tried a few approaches ranging from a strategy pattern for determining _context property, a factory pattern for constructing the DBset<T>, but it always falls apart because at the end of the day, I can't figure out a way to determine which _context property to use at the time of the upload.

I've also thought about inverting control to the objects themselves, so that all "File" objects can call their own Save(), but that's still overriding every filetype. Not bad, but there's got to be a better way. Note that all I'm doing on that line is mapping to the model, so maybe a Func<> for model mapping? Ugh.

There's also the possibility I shouldn't do it this way at all, and instead should just add a column to the database to indicate filetypes using a simple enum. I'm not a fan of this approach, but I have no legitimate reason for having a preference here.

EssOEss
Oct 23, 2006
128-bit approved
Inheritance in database object models never works out well. I suggest you restructure your model to not use it.

A solution consisting of comments like "These 3 fields are only used if Type==Image" works just fine and avoids a lot of bullshit.

downout
Jul 6, 2009

User0015 posted:

So I've ran into an issue trying to think of a good solution for the following problem, and I could use some general advice. Problem looks like this:

Model:
code:
 public class File
    {
        public Guid Id { get; set; }
        [Required]
        [StringLength(255)]
        public string FileName { get; set; }
        [Required]
        public byte[] Data { get; set; }

        public DateTime TimeStamp { get; set; }
    }

public class Image : File 
{}

public class Audio : File
{}
This simple File model is the basis for an EF context for storing files. As a file can have many types, I originally created a context that looks something like this:

code:
        public DbSet<Image> Images { get; set; }
        public DbSet<Audio> Audio { get; set; }
And of course, the service call

code:
private void MyGenericUploadMethod(IFormFileCollection files)
using (_context.Database.BeginTransaction())
            {
               //A BUNCH OF BULLSHIT HERE WHO CARES
		 _context.??????.Add(...); // <=== _context.Images? _context.Audio? _context.SlashFanFicts? I DONT KNOW
            }
        }
Here's the problem: the _context for EF needs to specify the property related to the table I want to use. If I have N file types I wish to store, I will need N service calls for N properties on _context, which literally all do the same thing, wrap transaction logic.

I could probably create a base class, but I can't find a way to create a more generic Upload method. I've tried a few approaches ranging from a strategy pattern for determining _context property, a factory pattern for constructing the DBset<T>, but it always falls apart because at the end of the day, I can't figure out a way to determine which _context property to use at the time of the upload.

I've also thought about inverting control to the objects themselves, so that all "File" objects can call their own Save(), but that's still overriding every filetype. Not bad, but there's got to be a better way. Note that all I'm doing on that line is mapping to the model, so maybe a Func<> for model mapping? Ugh.

There's also the possibility I shouldn't do it this way at all, and instead should just add a column to the database to indicate filetypes using a simple enum. I'm not a fan of this approach, but I have no legitimate reason for having a preference here.

I would think you would have to have a column in the database with the type. The database is essentially storing the data agnostic of type; it's just file data. This suggests that an artificially constructed TYPE string must be saved with each row of file data, whether that's in the same table or a referenced table.

Nth Doctor
Sep 7, 2010

Darkrai used Dream Eater!
It's super effective!


downout posted:

I would think you would have to have a column in the database with the type. The database is essentially storing the data agnostic of type; it's just file data. This suggests that an artificially constructed TYPE string must be saved with each row of file data, whether that's in the same table or a referenced table.

:yeah:
but a Type key FK'd to a Type table because ~*normalization*~

Adbot
ADBOT LOVES YOU

kloa
Feb 14, 2007


Do you need a Type field at all? Or can you just use MimeMapping on the FileName to determine it's type when it's being accessed?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply